From 94dc332105597a8b704351a010c00d84bcf9b34b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BE=E5=B0=8F=E5=83=A7?= Date: Thu, 8 Oct 2020 02:05:10 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20update=20documents.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/1ea356f4.3279ccd7.js | 1 - docs/1ea356f4.d84c9503.js | 1 + ...69f93.f969095c.js => 3e869f93.fc3e563c.js} | 2 +- docs/404.html | 4 +- ...cf072.ac2f7683.js => 4dbcf072.42badb24.js} | 2 +- docs/5ce0ebbd.1dfadef3.js | 1 + docs/5ce0ebbd.39ab69aa.js | 1 - ...b163f.4e02d840.js => 7b4b163f.a41ae4d5.js} | 2 +- docs/blog/index.html | 4 +- docs/blog/tags/fur/index.html | 4 +- docs/blog/tags/furos/index.html | 4 +- docs/blog/tags/index.html | 4 +- docs/blog/tags/net-5/index.html | 4 +- docs/blog/tags/net/index.html | 4 +- docs/blog/tags/netcore/index.html | 4 +- docs/blog/welcome/index.html | 4 +- docs/docs/aop/index.html | 4 +- docs/docs/appstartup/index.html | 37 +- docs/docs/auth-control/index.html | 4 +- docs/docs/author/index.html | 4 +- docs/docs/cache/index.html | 4 +- docs/docs/configuration/index.html | 4 +- docs/docs/contribute/index.html | 4 +- docs/docs/cors/index.html | 4 +- docs/docs/data-validation/index.html | 4 +- docs/docs/dbcontext-Interceptor/index.html | 10 +- docs/docs/dbcontext-add-or-update/index.html | 4 +- docs/docs/dbcontext-add/index.html | 4 +- docs/docs/dbcontext-audit/index.html | 4 +- docs/docs/dbcontext-batch/index.html | 4 +- docs/docs/dbcontext-code-first/index.html | 4 +- docs/docs/dbcontext-db-first/index.html | 4 +- docs/docs/dbcontext-delete/index.html | 4 +- docs/docs/dbcontext-filter/index.html | 4 +- docs/docs/dbcontext-function/index.html | 4 +- docs/docs/dbcontext-hight-query/index.html | 4 +- docs/docs/dbcontext-locator/index.html | 4 +- docs/docs/dbcontext-multi-database/index.html | 4 +- docs/docs/dbcontext-proc/index.html | 4 +- docs/docs/dbcontext-query/index.html | 4 +- docs/docs/dbcontext-read-write/index.html | 10 +- docs/docs/dbcontext-repository/index.html | 4 +- docs/docs/dbcontext-seed-data/index.html | 4 +- docs/docs/dbcontext-sql-proxy/index.html | 4 +- docs/docs/dbcontext-sql-template/index.html | 4 +- docs/docs/dbcontext-sql/index.html | 4 +- docs/docs/dbcontext-update/index.html | 4 +- docs/docs/dbcontext-view/index.html | 4 +- docs/docs/dbcontext/index.html | 14 +- docs/docs/dependency-injection/index.html | 4 +- docs/docs/deploy/index.html | 4 +- docs/docs/devops/index.html | 4 +- docs/docs/dynamic-api-controller/index.html | 4 +- docs/docs/entity/index.html | 4 +- docs/docs/event-bus/index.html | 4 +- docs/docs/friendly-exception/index.html | 4 +- docs/docs/get-start/index.html | 14 +- docs/docs/grpc/index.html | 4 +- docs/docs/index.html | 4 +- docs/docs/job/index.html | 4 +- docs/docs/local-language/index.html | 4 +- docs/docs/logging/index.html | 4 +- docs/docs/object-mapper/index.html | 4 +- docs/docs/options/index.html | 4 +- docs/docs/performance/index.html | 4 +- docs/docs/process-service/index.html | 4 +- docs/docs/saas/index.html | 14 +- docs/docs/signalr/index.html | 4 +- docs/docs/source/index.html | 4 +- docs/docs/specification-document/index.html | 4 +- docs/docs/split-db/index.html | 4 +- docs/docs/tran/index.html | 4 +- docs/docs/unittest/index.html | 4 +- docs/docs/view-engine/index.html | 4 +- docs/f9353588.f01f83d1.js | 1 + docs/f9353588.f7d5daf4.js | 1 - docs/index.html | 4 +- ...n.6df32296.js => runtime~main.a44330c3.js} | 2 +- .../Fur.Application/FurApplicationStartup.cs | 2 +- framework/Fur.Core/FurCoreStartup.cs | 2 +- .../FurEntityFrameworkCoreStartup.cs | 2 +- framework/Fur.Web.Core/FurWebCoreStartup.cs | 2 +- ...tupAttribute.cs => AppStartupAttribute.cs} | 9 +- .../AppServiceCollectionExtensions.cs | 4 +- framework/Fur/FurStartup.cs | 2 +- handbook/build/1ea356f4.cbd9b1c3.js | 1 - handbook/build/1ea356f4.cdf2ad5e.js | 1 + ...69f93.43ad9133.js => 3e869f93.3b6f6bba.js} | 2 +- handbook/build/404.html | 4 +- ...cf072.c0f2f064.js => 4dbcf072.19b891a9.js} | 2 +- handbook/build/5ce0ebbd.355b0f5e.js | 1 + handbook/build/5ce0ebbd.5a25ca36.js | 1 - ...b163f.afa932db.js => 7b4b163f.d5d1e2bf.js} | 2 +- handbook/build/blog/index.html | 4 +- handbook/build/blog/tags/fur/index.html | 4 +- handbook/build/blog/tags/furos/index.html | 4 +- handbook/build/blog/tags/index.html | 4 +- handbook/build/blog/tags/net-5/index.html | 4 +- handbook/build/blog/tags/net/index.html | 4 +- handbook/build/blog/tags/netcore/index.html | 4 +- handbook/build/blog/welcome/index.html | 4 +- handbook/build/docs/aop/index.html | 4 +- handbook/build/docs/appstartup/index.html | 37 +- handbook/build/docs/auth-control/index.html | 4 +- handbook/build/docs/author/index.html | 4 +- handbook/build/docs/cache/index.html | 4 +- handbook/build/docs/configuration/index.html | 4 +- handbook/build/docs/contribute/index.html | 4 +- handbook/build/docs/cors/index.html | 4 +- .../build/docs/data-validation/index.html | 4 +- .../docs/dbcontext-Interceptor/index.html | 10 +- .../docs/dbcontext-add-or-update/index.html | 4 +- handbook/build/docs/dbcontext-add/index.html | 4 +- .../build/docs/dbcontext-audit/index.html | 4 +- .../build/docs/dbcontext-batch/index.html | 4 +- .../docs/dbcontext-code-first/index.html | 4 +- .../build/docs/dbcontext-db-first/index.html | 4 +- .../build/docs/dbcontext-delete/index.html | 4 +- .../build/docs/dbcontext-filter/index.html | 4 +- .../build/docs/dbcontext-function/index.html | 4 +- .../docs/dbcontext-hight-query/index.html | 4 +- .../build/docs/dbcontext-locator/index.html | 4 +- .../docs/dbcontext-multi-database/index.html | 4 +- handbook/build/docs/dbcontext-proc/index.html | 4 +- .../build/docs/dbcontext-query/index.html | 4 +- .../docs/dbcontext-read-write/index.html | 10 +- .../docs/dbcontext-repository/index.html | 4 +- .../build/docs/dbcontext-seed-data/index.html | 4 +- .../build/docs/dbcontext-sql-proxy/index.html | 4 +- .../docs/dbcontext-sql-template/index.html | 4 +- handbook/build/docs/dbcontext-sql/index.html | 4 +- .../build/docs/dbcontext-update/index.html | 4 +- handbook/build/docs/dbcontext-view/index.html | 4 +- handbook/build/docs/dbcontext/index.html | 14 +- .../docs/dependency-injection/index.html | 4 +- handbook/build/docs/deploy/index.html | 4 +- handbook/build/docs/devops/index.html | 4 +- .../docs/dynamic-api-controller/index.html | 4 +- handbook/build/docs/entity/index.html | 4 +- handbook/build/docs/event-bus/index.html | 4 +- .../build/docs/friendly-exception/index.html | 4 +- handbook/build/docs/get-start/index.html | 14 +- handbook/build/docs/grpc/index.html | 4 +- handbook/build/docs/index.html | 4 +- handbook/build/docs/job/index.html | 4 +- handbook/build/docs/local-language/index.html | 4 +- handbook/build/docs/logging/index.html | 4 +- handbook/build/docs/object-mapper/index.html | 4 +- handbook/build/docs/options/index.html | 4 +- handbook/build/docs/performance/index.html | 4 +- .../build/docs/process-service/index.html | 4 +- handbook/build/docs/saas/index.html | 14 +- handbook/build/docs/signalr/index.html | 4 +- handbook/build/docs/source/index.html | 4 +- .../docs/specification-document/index.html | 4 +- handbook/build/docs/split-db/index.html | 4 +- handbook/build/docs/tran/index.html | 4 +- handbook/build/docs/unittest/index.html | 4 +- handbook/build/docs/view-engine/index.html | 4 +- handbook/build/f9353588.35659a55.js | 1 - handbook/build/f9353588.433ee201.js | 1 + handbook/build/index.html | 4 +- ...n.f6cd1698.js => runtime~main.1ff2adeb.js} | 2 +- handbook/docs/appstartup.mdx | 345 ++++++++++++++++++ handbook/docs/dbcontext-Interceptor.mdx | 2 +- handbook/docs/dbcontext-read-write.mdx | 2 +- handbook/docs/dbcontext.mdx | 6 +- handbook/docs/get-start.mdx | 2 +- handbook/docs/saas.mdx | 6 +- 169 files changed, 749 insertions(+), 359 deletions(-) delete mode 100644 docs/1ea356f4.3279ccd7.js create mode 100644 docs/1ea356f4.d84c9503.js rename docs/{3e869f93.f969095c.js => 3e869f93.fc3e563c.js} (51%) rename docs/{4dbcf072.ac2f7683.js => 4dbcf072.42badb24.js} (54%) create mode 100644 docs/5ce0ebbd.1dfadef3.js delete mode 100644 docs/5ce0ebbd.39ab69aa.js rename docs/{7b4b163f.4e02d840.js => 7b4b163f.a41ae4d5.js} (99%) create mode 100644 docs/f9353588.f01f83d1.js delete mode 100644 docs/f9353588.f7d5daf4.js rename docs/{runtime~main.6df32296.js => runtime~main.a44330c3.js} (93%) rename framework/Fur/App/Attributes/{StartupAttribute.cs => AppStartupAttribute.cs} (83%) delete mode 100644 handbook/build/1ea356f4.cbd9b1c3.js create mode 100644 handbook/build/1ea356f4.cdf2ad5e.js rename handbook/build/{3e869f93.43ad9133.js => 3e869f93.3b6f6bba.js} (51%) rename handbook/build/{4dbcf072.c0f2f064.js => 4dbcf072.19b891a9.js} (54%) create mode 100644 handbook/build/5ce0ebbd.355b0f5e.js delete mode 100644 handbook/build/5ce0ebbd.5a25ca36.js rename handbook/build/{7b4b163f.afa932db.js => 7b4b163f.d5d1e2bf.js} (99%) delete mode 100644 handbook/build/f9353588.35659a55.js create mode 100644 handbook/build/f9353588.433ee201.js rename handbook/build/{runtime~main.f6cd1698.js => runtime~main.1ff2adeb.js} (65%) diff --git a/docs/1ea356f4.3279ccd7.js b/docs/1ea356f4.3279ccd7.js deleted file mode 100644 index 6aafc8dde59..00000000000 --- a/docs/1ea356f4.3279ccd7.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[14],{138:function(e,n,t){"use strict";t.d(n,"a",(function(){return d})),t.d(n,"b",(function(){return m}));var a=t(0),i=t.n(a);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 c(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 s=i.a.createContext({}),l=function(e){var n=i.a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):c(c({},n),e)),t},d=function(e){var n=l(e.components);return i.a.createElement(s.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return i.a.createElement(i.a.Fragment,{},n)}},u=i.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,r=e.originalType,o=e.parentName,s=b(e,["components","mdxType","originalType","parentName"]),d=l(t),u=a,m=d["".concat(o,".").concat(u)]||d[u]||p[u]||r;return t?i.a.createElement(m,c(c({ref:n},s),{},{components:t})):i.a.createElement(m,c({ref:n},s))}));function m(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var r=t.length,o=new Array(r);o[0]=u;var c={};for(var b in n)hasOwnProperty.call(n,b)&&(c[b]=n[b]);c.originalType=e,c.mdxType="string"==typeof e?e:a,o[1]=c;for(var s=2;sfunction(e,n,t,{forcePrependBaseUrl:a=!1,absolute:r=!1}={}){if(!t)return t;if(t.startsWith("#"))return t;if(Object(i.b)(t))return t;if(a)return n+t;const o=t.startsWith(n)?t:n+t.replace(/^\//,"");return r?e+o:o}(n,e,t,a)}}function o(e,n={}){const{withBaseUrl:t}=r();return t(e,n)}},141:function(e,n,t){"use strict";function a(e){return!0===/^(\w*:|\/\/)/.test(e)}function i(e){return void 0!==e&&!a(e)}t.d(n,"b",(function(){return a})),t.d(n,"a",(function(){return i}))},69:function(e,n,t){"use strict";t.r(n),t.d(n,"frontMatter",(function(){return c})),t.d(n,"metadata",(function(){return b})),t.d(n,"rightToc",(function(){return s})),t.d(n,"default",(function(){return d}));var a=t(2),i=t(6),r=(t(0),t(138)),o=t(140),c={id:"saas",title:"10. SaaS \u591a\u79df\u6237",sidebar_label:"10. SaaS \u591a\u79df\u6237"},b={unversionedId:"saas",id:"saas",isDocsHomePage:!1,title:"10. SaaS \u591a\u79df\u6237",description:"10.1 \u4ec0\u4e48\u662f SaaS",source:"@site/docs\\saas.mdx",slug:"/saas",permalink:"/docs/saas",editUrl:"https://gitee.com/monksoul/Fur/tree/main/handbook/docs/saas.mdx",version:"current",sidebar_label:"10. SaaS \u591a\u79df\u6237",sidebar:"docs",previous:{title:"9.27 \u5206\u8868\u5206\u5e93",permalink:"/docs/split-db"},next:{title:"11. \u4f9d\u8d56\u6ce8\u5165/\u63a7\u5236\u53cd\u8f6c",permalink:"/docs/dependency-injection"}},s=[{value:"10.1 \u4ec0\u4e48\u662f SaaS",id:"101-\u4ec0\u4e48\u662f-saas",children:[]},{value:"10.2 \u4ec0\u4e48\u662f\u591a\u79df\u6237",id:"102-\u4ec0\u4e48\u662f\u591a\u79df\u6237",children:[]},{value:"10.3 \u5b9e\u73b0\u591a\u79df\u6237\u65b9\u6848",id:"103-\u5b9e\u73b0\u591a\u79df\u6237\u65b9\u6848",children:[{value:"10.3.1 \u72ec\u7acb\u6570\u636e\u5e93",id:"1031-\u72ec\u7acb\u6570\u636e\u5e93",children:[]},{value:"10.3.2 \u5171\u4eab\u6570\u636e\u5e93\uff0c\u72ec\u7acb Schema",id:"1032-\u5171\u4eab\u6570\u636e\u5e93\uff0c\u72ec\u7acb-schema",children:[]},{value:"10.3.3 \u5171\u4eab\u6570\u636e\u5e93\uff0c\u5171\u4eab Schema",id:"1033-\u5171\u4eab\u6570\u636e\u5e93\uff0c\u5171\u4eab-schema",children:[]}]},{value:"10.4 \u591a\u79df\u6237\u4f7f\u7528\u65b9\u6848",id:"104-\u591a\u79df\u6237\u4f7f\u7528\u65b9\u6848",children:[]},{value:"10.5 \u57fa\u4e8e TenantId \u7684\u65b9\u5f0f",id:"105-\u57fa\u4e8e-tenantid-\u7684\u65b9\u5f0f",children:[{value:"10.5.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1051-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.5.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1052-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.5.3 \u6dfb\u52a0 Tenant \u79cd\u5b50\u6570\u636e",id:"1053-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e",children:[]},{value:"10.5.4 \u6839\u636e\u6a21\u578b\u521b\u5efa Tenant \u8868",id:"1054-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868",children:[]},{value:"10.5.5 \u5b9e\u73b0 IMultiTenantOnTable \u63a5\u53e3",id:"1055-\u5b9e\u73b0-imultitenantontable-\u63a5\u53e3",children:[]},{value:"10.5.6 \u5b9e\u73b0 IModelBuilderFilter \u63a5\u53e3",id:"1056-\u5b9e\u73b0-imodelbuilderfilter-\u63a5\u53e3",children:[]},{value:"10.5.7 \u91cd\u5199 SavingChangesEvent \u4e8b\u4ef6\u65b9\u6cd5",id:"1057-\u91cd\u5199-savingchangesevent-\u4e8b\u4ef6\u65b9\u6cd5",children:[]}]},{value:"10.6 \u57fa\u4e8e Database \u7684\u65b9\u5f0f",id:"106-\u57fa\u4e8e-database-\u7684\u65b9\u5f0f",children:[{value:"10.6.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1061-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.6.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1062-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.6.3 \u6dfb\u52a0 Tenant \u79cd\u5b50\u6570\u636e",id:"1063-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e",children:[]},{value:"10.6.4 \u6839\u636e\u6a21\u578b\u521b\u5efa Tenant \u8868",id:"1064-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868",children:[]},{value:"10.6.5 \u5b9e\u73b0 IMultiTenantOnDatabase \u63a5\u53e3",id:"1065-\u5b9e\u73b0-imultitenantondatabase-\u63a5\u53e3",children:[]},{value:"10.6.6 \u91cd\u5199 OnConfiguring \u65b9\u6cd5",id:"1066-\u91cd\u5199-onconfiguring-\u65b9\u6cd5",children:[]}]},{value:"10.7 \u57fa\u4e8e Schema \u7684\u65b9\u5f0f",id:"107-\u57fa\u4e8e-schema-\u7684\u65b9\u5f0f",children:[{value:"10.7.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1071-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.7.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1072-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.7.3 \u6dfb\u52a0 Tenant \u79cd\u5b50\u6570\u636e",id:"1073-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e",children:[]},{value:"10.7.4 \u6839\u636e\u6a21\u578b\u521b\u5efa Tenant \u8868",id:"1074-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868",children:[]},{value:"10.7.5 \u5b9e\u73b0 IMultiTenantOnSchema \u63a5\u53e3",id:"1075-\u5b9e\u73b0-imultitenantonschema-\u63a5\u53e3",children:[]},{value:"10.7.6 \u5173\u4e8e Code First \u6570\u636e\u8fc1\u79fb",id:"1076-\u5173\u4e8e-code-first-\u6570\u636e\u8fc1\u79fb",children:[]}]},{value:"10.8 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"108-\u53cd\u9988\u4e0e\u5efa\u8bae",children:[]}],l={rightToc:s};function d(e){var n=e.components,t=Object(i.a)(e,["components"]);return Object(r.b)("wrapper",Object(a.a)({},l,t,{components:n,mdxType:"MDXLayout"}),Object(r.b)("h2",{id:"101-\u4ec0\u4e48\u662f-saas"},"10.1 \u4ec0\u4e48\u662f ",Object(r.b)("inlineCode",{parentName:"h2"},"SaaS")),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"SaaS \u662f Software-as-a-Service\uff08\u8f6f\u4ef6\u5373\u670d\u52a1\uff09\u7684\u7b80\u79f0\uff0c\u968f\u7740\u4e92\u8054\u7f51\u6280\u672f\u7684\u53d1\u5c55\u548c\u5e94\u7528\u8f6f\u4ef6\u7684\u6210\u719f\uff0c \u5728 21 \u4e16\u7eaa\u5f00\u59cb\u5174\u8d77\u7684\u4e00\u79cd\u5b8c\u5168\u521b\u65b0\u7684\u8f6f\u4ef6\u5e94\u7528\u6a21\u5f0f\u3002\u5b83\u4e0e\u201con-demand software\u201d\uff0cthe application service provider(ASP\uff0c\u5e94\u7528\u670d\u52a1\u63d0\u4f9b\u5546)\uff0chosted software(\u6258\u7ba1\u8f6f\u4ef6)\u6240\u5177\u6709\u76f8\u4f3c\u7684\u542b\u4e49\u3002"),Object(r.b)("p",{parentName:"blockquote"},"\u5b83\u662f\u4e00\u79cd\u901a\u8fc7 Internet \u63d0\u4f9b\u8f6f\u4ef6\u7684\u6a21\u5f0f\uff0c\u5382\u5546\u5c06\u5e94\u7528\u8f6f\u4ef6\u7edf\u4e00\u90e8\u7f72\u5728\u81ea\u5df1\u7684\u670d\u52a1\u5668\u4e0a\uff0c\u5ba2\u6237\u53ef\u4ee5\u6839\u636e\u81ea\u5df1\u5b9e\u9645\u9700\u6c42\uff0c\u901a\u8fc7\u4e92\u8054\u7f51\u5411\u5382\u5546\u5b9a\u8d2d\u6240\u9700\u7684\u5e94\u7528\u8f6f\u4ef6\u670d\u52a1\uff0c\u6309\u5b9a\u8d2d\u7684\u670d\u52a1\u591a\u5c11\u548c\u65f6\u95f4\u957f\u77ed\u5411\u5382\u5546\u652f\u4ed8\u8d39\u7528\uff0c\u5e76\u901a\u8fc7\u4e92\u8054\u7f51\u83b7\u5f97\u5382\u5546\u63d0\u4f9b\u7684\u670d\u52a1\u3002\u7528\u6237\u4e0d\u7528\u518d\u8d2d\u4e70\u8f6f\u4ef6\uff0c\u800c\u6539\u7528\u5411\u63d0\u4f9b\u5546\u79df\u7528\u57fa\u4e8e Web \u7684\u8f6f\u4ef6\uff0c\u6765\u7ba1\u7406\u4f01\u4e1a\u7ecf\u8425\u6d3b\u52a8\uff0c\u4e14\u65e0\u9700\u5bf9\u8f6f\u4ef6\u8fdb\u884c\u7ef4\u62a4\uff0c\u670d\u52a1\u63d0\u4f9b\u5546\u4f1a\u5168\u6743\u7ba1\u7406\u548c\u7ef4\u62a4\u8f6f\u4ef6\uff0c\u8f6f\u4ef6\u5382\u5546\u5728\u5411\u5ba2\u6237\u63d0\u4f9b\u4e92\u8054\u7f51\u5e94\u7528\u7684\u540c\u65f6\uff0c\u4e5f\u63d0\u4f9b\u8f6f\u4ef6\u7684\u79bb\u7ebf\u64cd\u4f5c\u548c\u672c\u5730\u6570\u636e\u5b58\u50a8\uff0c\u8ba9\u7528\u6237\u968f\u65f6\u968f\u5730\u90fd\u53ef\u4ee5\u4f7f\u7528\u5176\u5b9a\u8d2d\u7684\u8f6f\u4ef6\u548c\u670d\u52a1\u3002"),Object(r.b)("p",{parentName:"blockquote"},"\u5bf9\u4e8e\u8bb8\u591a\u5c0f\u578b\u4f01\u4e1a\u6765\u8bf4\uff0cSaaS \u662f\u91c7\u7528\u5148\u8fdb\u6280\u672f\u7684\u6700\u597d\u9014\u5f84\uff0c\u5b83\u6d88\u9664\u4e86\u4f01\u4e1a\u8d2d\u4e70\u3001\u6784\u5efa\u548c\u7ef4\u62a4\u57fa\u7840\u8bbe\u65bd\u548c\u5e94\u7528\u7a0b\u5e8f\u7684\u9700\u8981\u3002")),Object(r.b)("h2",{id:"102-\u4ec0\u4e48\u662f\u591a\u79df\u6237"},"10.2 \u4ec0\u4e48\u662f\u591a\u79df\u6237"),Object(r.b)("p",null,"\u591a\u79df\u6237\u6280\u672f\u6216\u79f0\u591a\u91cd\u79df\u8d41\u6280\u672f\uff0c\u7b80\u79f0 ",Object(r.b)("inlineCode",{parentName:"p"},"SaaS"),"\uff0c\u662f\u4e00\u79cd\u8f6f\u4ef6\u67b6\u6784\u6280\u672f\uff0c\u662f\u5b9e\u73b0\u5982\u4f55\u5728\u591a\u7528\u6237\u73af\u5883\u4e0b\uff08\u6b64\u5904\u7684\u591a\u7528\u6237\u4e00\u822c\u662f\u9762\u5411\u4f01\u4e1a\u7528\u6237\uff09\u5171\u7528\u76f8\u540c\u7684\u7cfb\u7edf\u6216\u7a0b\u5e8f\u7ec4\u4ef6\uff0c\u5e76\u4e14\u53ef\u786e\u4fdd\u5404\u7528\u6237\u95f4\u6570\u636e\u7684\u9694\u79bb\u6027\u3002"),Object(r.b)("p",null,Object(r.b)("strong",{parentName:"p"},"\u7b80\u5355\u8bb2\uff1a\u5728\u4e00\u53f0\u670d\u52a1\u5668\u4e0a\u8fd0\u884c\u5355\u4e2a\u5e94\u7528\u5b9e\u4f8b\uff0c\u5b83\u4e3a\u591a\u4e2a\u79df\u6237\uff08\u5ba2\u6237\uff09\u63d0\u4f9b\u670d\u52a1\u3002"),"\u4ece\u5b9a\u4e49\u4e2d\u6211\u4eec\u53ef\u4ee5\u7406\u89e3\uff1a\u591a\u79df\u6237\u662f\u4e00\u79cd\u67b6\u6784\uff0c\u76ee\u7684\u662f\u4e3a\u4e86\u8ba9\u591a\u7528\u6237\u73af\u5883\u4e0b\u4f7f\u7528\u540c\u4e00\u5957\u7a0b\u5e8f\uff0c\u4e14\u4fdd\u8bc1\u7528\u6237\u95f4\u6570\u636e\u9694\u79bb\u3002\u90a3\u4e48\u91cd\u70b9\u5c31\u5f88\u6d45\u663e\u6613\u61c2\u4e86\uff0c\u591a\u79df\u6237\u7684\u91cd\u70b9\u5c31\u662f\u540c\u4e00\u5957\u7a0b\u5e8f\u4e0b\u5b9e\u73b0\u591a\u7528\u6237\u6570\u636e\u7684\u9694\u79bb\u3002"),Object(r.b)("h2",{id:"103-\u5b9e\u73b0\u591a\u79df\u6237\u65b9\u6848"},"10.3 \u5b9e\u73b0\u591a\u79df\u6237\u65b9\u6848"),Object(r.b)("h3",{id:"1031-\u72ec\u7acb\u6570\u636e\u5e93"},"10.3.1 \u72ec\u7acb\u6570\u636e\u5e93"),Object(r.b)("p",null,"\u8fd9\u662f\u7b2c\u4e00\u79cd\u65b9\u6848\uff0c\u5373\u4e00\u4e2a\u79df\u6237\u4e00\u4e2a\u6570\u636e\u5e93\uff0c\u8fd9\u79cd\u65b9\u6848\u7684\u7528\u6237\u6570\u636e\u9694\u79bb\u7ea7\u522b\u6700\u9ad8\uff0c\u5b89\u5168\u6027\u6700\u597d\uff0c\u4f46\u6210\u672c\u8f83\u9ad8\u3002"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u4f18\u70b9\uff1a"),"\n\u4e3a\u4e0d\u540c\u7684\u79df\u6237\u63d0\u4f9b\u72ec\u7acb\u7684\u6570\u636e\u5e93\uff0c\u6709\u52a9\u4e8e\u7b80\u5316\u6570\u636e\u6a21\u578b\u7684\u6269\u5c55\u8bbe\u8ba1\uff0c\u6ee1\u8db3\u4e0d\u540c\u79df\u6237\u7684\u72ec\u7279\u9700\u6c42\uff1b\u5982\u679c\u51fa\u73b0\u6545\u969c\uff0c\u6062\u590d\u6570\u636e\u6bd4\u8f83\u7b80\u5355\u3002")),Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u7f3a\u70b9\uff1a"),"\n\u589e\u591a\u4e86\u6570\u636e\u5e93\u7684\u5b89\u88c5\u6570\u91cf\uff0c\u968f\u4e4b\u5e26\u6765\u7ef4\u62a4\u6210\u672c\u548c\u8d2d\u7f6e\u6210\u672c\u7684\u589e\u52a0\u3002 \u8fd9\u79cd\u65b9\u6848\u4e0e\u4f20\u7edf\u7684\u4e00\u4e2a\u5ba2\u6237\u3001\u4e00\u5957\u6570\u636e\u3001\u4e00\u5957\u90e8\u7f72\u7c7b\u4f3c\uff0c\u5dee\u522b\u53ea\u5728\u4e8e\u8f6f\u4ef6\u7edf\u4e00\u90e8\u7f72\u5728\u8fd0\u8425\u5546\u90a3\u91cc\u3002\u5982\u679c\u9762\u5bf9\u7684\u662f\u94f6\u884c\u3001\u533b\u9662\u7b49\u9700\u8981\u975e\u5e38\u9ad8\u6570\u636e\u9694\u79bb\u7ea7\u522b\u7684\u79df\u6237\uff0c\u53ef\u4ee5\u9009\u62e9\u8fd9\u79cd\u6a21\u5f0f\uff0c\u63d0\u9ad8\u79df\u7528\u7684\u5b9a\u4ef7\u3002\u5982\u679c\u5b9a\u4ef7\u8f83\u4f4e\uff0c\u4ea7\u54c1\u8d70\u4f4e\u4ef7\u8def\u7ebf\uff0c\u8fd9\u79cd\u65b9\u6848\u4e00\u822c\u5bf9\u8fd0\u8425\u5546\u6765\u8bf4\u662f\u65e0\u6cd5\u627f\u53d7\u7684\u3002"))),Object(r.b)("h3",{id:"1032-\u5171\u4eab\u6570\u636e\u5e93\uff0c\u72ec\u7acb-schema"},"10.3.2 \u5171\u4eab\u6570\u636e\u5e93\uff0c\u72ec\u7acb ",Object(r.b)("inlineCode",{parentName:"h3"},"Schema")),Object(r.b)("p",null,"\u8fd9\u662f\u7b2c\u4e8c\u79cd\u65b9\u6848\uff0c\u5373\u591a\u4e2a\u6216\u6240\u6709\u79df\u6237\u5171\u4eab ",Object(r.b)("inlineCode",{parentName:"p"},"Database"),"\uff0c\u4f46\u662f\u6bcf\u4e2a\u79df\u6237\u4e00\u4e2a ",Object(r.b)("inlineCode",{parentName:"p"},"Schema"),"\uff08\u4e5f\u53ef\u53eb\u505a\u4e00\u4e2a user\uff09\u3002\u5e95\u5c42\u5e93\u6bd4\u5982\u662f\uff1a",Object(r.b)("inlineCode",{parentName:"p"},"SqlServer"),"\u3001",Object(r.b)("inlineCode",{parentName:"p"},"Oracle")," \u7b49\uff0c\u4e00\u4e2a\u6570\u636e\u5e93\u4e0b\u53ef\u4ee5\u6709\u591a\u4e2a ",Object(r.b)("inlineCode",{parentName:"p"},"Schema"),"\u3002"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u4f18\u70b9\uff1a"),"\n\u4e3a\u5b89\u5168\u6027\u8981\u6c42\u8f83\u9ad8\u7684\u79df\u6237\u63d0\u4f9b\u4e86\u4e00\u5b9a\u7a0b\u5ea6\u7684\u903b\u8f91\u6570\u636e\u9694\u79bb\uff0c\u5e76\u4e0d\u662f\u5b8c\u5168\u9694\u79bb\uff1b\u6bcf\u4e2a\u6570\u636e\u5e93\u53ef\u652f\u6301\u66f4\u591a\u7684\u79df\u6237\u6570\u91cf\u3002")),Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u7f3a\u70b9\uff1a"),"\n\u5982\u679c\u51fa\u73b0\u6545\u969c\uff0c\u6570\u636e\u6062\u590d\u6bd4\u8f83\u56f0\u96be\uff0c\u56e0\u4e3a\u6062\u590d\u6570\u636e\u5e93\u5c06\u7275\u6d89\u5230\u5176\u4ed6\u79df\u6237\u7684\u6570\u636e\uff1b \u5982\u679c\u9700\u8981\u8de8\u79df\u6237\u7edf\u8ba1\u6570\u636e\uff0c\u5b58\u5728\u4e00\u5b9a\u56f0\u96be\u3002"))),Object(r.b)("h3",{id:"1033-\u5171\u4eab\u6570\u636e\u5e93\uff0c\u5171\u4eab-schema"},"10.3.3 \u5171\u4eab\u6570\u636e\u5e93\uff0c\u5171\u4eab ",Object(r.b)("inlineCode",{parentName:"h3"},"Schema")),Object(r.b)("p",null,"\u5171\u4eab\u6570\u636e\u8868 \u8fd9\u662f\u7b2c\u4e09\u79cd\u65b9\u6848\uff0c\u5373\u79df\u6237\u5171\u4eab\u540c\u4e00\u4e2a ",Object(r.b)("inlineCode",{parentName:"p"},"Database"),"\u3001\u540c\u4e00\u4e2a ",Object(r.b)("inlineCode",{parentName:"p"},"Schema"),"\uff0c\u4f46\u5728\u8868\u4e2d\u589e\u52a0 ",Object(r.b)("strong",{parentName:"p"},Object(r.b)("inlineCode",{parentName:"strong"},"TenantId"))," \u591a\u79df\u6237\u7684\u6570\u636e\u5b57\u6bb5\u3002\u8fd9\u662f\u5171\u4eab\u7a0b\u5ea6\u6700\u9ad8\u3001\u9694\u79bb\u7ea7\u522b\u6700\u4f4e\u7684\u6a21\u5f0f\u3002 \u5373\u6bcf\u63d2\u5165\u4e00\u6761\u6570\u636e\u65f6\u90fd\u9700\u8981\u6709\u4e00\u4e2a\u5ba2\u6237\u7684\u6807\u8bc6\u3002\u8fd9\u6837\u624d\u80fd\u5728\u540c\u4e00\u5f20\u8868\u4e2d\u533a\u5206\u51fa\u4e0d\u540c\u5ba2\u6237\u7684\u6570\u636e\u3002"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u4f18\u70b9\uff1a"),"\n\u4e09\u79cd\u65b9\u6848\u6bd4\u8f83\uff0c\u7b2c\u4e09\u79cd\u65b9\u6848\u7684\u7ef4\u62a4\u548c\u8d2d\u7f6e\u6210\u672c\u6700\u4f4e\uff0c\u5141\u8bb8\u6bcf\u4e2a\u6570\u636e\u5e93\u652f\u6301\u7684\u79df\u6237\u6570\u91cf\u6700\u591a\u3002")),Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u7f3a\u70b9\uff1a"),"\n\u9694\u79bb\u7ea7\u522b\u6700\u4f4e\uff0c\u5b89\u5168\u6027\u6700\u4f4e\uff0c\u9700\u8981\u5728\u8bbe\u8ba1\u5f00\u53d1\u65f6\u52a0\u5927\u5bf9\u5b89\u5168\u7684\u5f00\u53d1\u91cf\uff1b \u6570\u636e\u5907\u4efd\u548c\u6062\u590d\u6700\u56f0\u96be\uff0c\u9700\u8981\u9010\u8868\u9010\u6761\u5907\u4efd\u548c\u8fd8\u539f\u3002"))),Object(r.b)("h2",{id:"104-\u591a\u79df\u6237\u4f7f\u7528\u65b9\u6848"},"10.4 \u591a\u79df\u6237\u4f7f\u7528\u65b9\u6848"),Object(r.b)("p",null,Object(r.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u652f\u6301\u4ee5\u4e0a\u4e09\u79cd\u591a\u79df\u6237\u5b9e\u73b0\u65b9\u6848\uff0c\u4f7f\u7528\u7b80\u5355\u4e14\u5bb9\u6613\u7ef4\u62a4\u3002\u4e0b\u9762\u5206\u522b\u4f7f\u7528\u4e09\u79cd\u4e0d\u540c\u65b9\u5f0f\u6f14\u793a\u591a\u79df\u6237\u65b9\u6848\u7528\u6cd5\u3002"),Object(r.b)("h2",{id:"105-\u57fa\u4e8e-tenantid-\u7684\u65b9\u5f0f"},"10.5 \u57fa\u4e8e ",Object(r.b)("inlineCode",{parentName:"h2"},"TenantId")," \u7684\u65b9\u5f0f"),Object(r.b)("p",null,"\u6b64\u65b9\u5f0f\u5728\u4e2d\u5c0f\u578b\u4f01\u4e1a\u7cfb\u7edf\u4e2d\u6700\u4e3a\u5e38\u7528\uff0c\u7ef4\u62a4\u6210\u672c\u4f4e\uff0c\u8d2d\u7f6e\u6210\u672c\u4f4e\u3002"),Object(r.b)("h3",{id:"1051-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.5.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{6-7} title="Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"',"{6-7}":!0,title:'"Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class MultiTenantDbContext : AppDbContext\n {\n public MultiTenantDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-important alert alert--info"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u591a\u79df\u6237\u64cd\u4f5c\u5efa\u8bae\u5355\u72ec\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u800c\u4e14\u9700\u6307\u5b9a ",Object(r.b)("inlineCode",{parentName:"p"},"MultiTenantDbContextLocator")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u3002"))),Object(r.b)("h3",{id:"1052-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.5.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{14}","{14}":!0}),"using Fur.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.EntityFramework.Core\n{\n [Startup(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 options.AddDbPool(DbProvider.Sqlite);\n });\n }\n }\n}\n")),Object(r.b)("h3",{id:"1053-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e"},"10.5.3 \u6dfb\u52a0 ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u79cd\u5b50\u6570\u636e"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{8,12-28} title="Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"',"{8,12-28}":!0,title:'"Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Fur.EntityFramework.Core\n{\n public class TenantSeedData : IEntitySeedData\n {\n public IEnumerable HasData(DbContext dbContext, Type dbContextLocator)\n {\n return new List\n {\n new Tenant\n {\n TenantId=Guid.Parse("383AFB88-F519-FFF8-B364-6D563BF3687F"),\n Name="\u9ed8\u8ba4\u79df\u6237",\n Host="localhost:44313",\n CreatedTime=DateTime.Parse("2020-10-06 20:19:07")\n },\n new Tenant\n {\n TenantId=Guid.Parse("C5798CB6-16D6-0F42-EB56-59C695353BC0"),\n Name="\u5176\u4ed6\u79df\u6237",\n Host="localhost:5000",\n CreatedTime=DateTime.Parse("2020-10-06 20:20:32")\n }\n };\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u8bf4\u660e")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u8be5\u6b65\u9aa4\u53ea\u5728 ",Object(r.b)("inlineCode",{parentName:"p"},"Code First")," \u65b9\u5f0f\u6267\u884c\uff0c",Object(r.b)("inlineCode",{parentName:"p"},"Database First")," \u65e0\u9700\u914d\u7f6e\u79cd\u5b50\u6570\u636e\u3002"))),Object(r.b)("h3",{id:"1054-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868"},"10.5.4 \u6839\u636e\u6a21\u578b\u521b\u5efa ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u8868"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Add-Migration add_tenant_table -Context MultiTenantDbContext\n")),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Update-Database -Context MultiTenantDbContext\n")),Object(r.b)("h3",{id:"1055-\u5b9e\u73b0-imultitenantontable-\u63a5\u53e3"},"10.5.5 \u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"h3"},"IMultiTenantOnTable")," \u63a5\u53e3"),Object(r.b)("p",null,"\u5728\u9700\u8981\u591a\u79df\u6237\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"p"},"IMultiTenantOnTable")," \u63a5\u53e3\uff0c\u5982\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{8,14-17}","{8,14-17}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing System;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class FurDbContext : AppDbContext, IMultiTenantOnTable, IModelBuilderFilter\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public Guid? GetTenantId()\n {\n return base.Tenant.TenantId;\n }\n }\n}\n')),Object(r.b)("p",null,"\u5728 ",Object(r.b)("inlineCode",{parentName:"p"},"GetTenantId()")," \u65b9\u6cd5\u4e2d\uff0c\u9996\u5148\u83b7\u53d6\u8bf7\u6c42\u7684 ",Object(r.b)("inlineCode",{parentName:"p"},"\u4e3b\u673a\u5730\u5740"),"\uff0c\u7136\u540e\u6839\u636e\u4e3b\u673a\u5730\u5740\u67e5\u8be2\u5bf9\u5e94\u7684\u79df\u6237 ",Object(r.b)("inlineCode",{parentName:"p"},"TenantIdId"),"\uff0c\u907f\u514d\u591a\u6b21\u67e5\u8be2\u6570\u636e\u5e93\uff0c\u8fd9\u91cc\u4f7f\u7528\u4e86 ",Object(r.b)("inlineCode",{parentName:"p"},"IMemoryCache")," \u5185\u5b58\u7f13\u5b58\u3002"),Object(r.b)("h3",{id:"1056-\u5b9e\u73b0-imodelbuilderfilter-\u63a5\u53e3"},"10.5.6 \u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"h3"},"IModelBuilderFilter")," \u63a5\u53e3"),Object(r.b)("p",null,Object(r.b)("inlineCode",{parentName:"p"},"IModelBuilderFilter")," \u63a5\u53e3\u662f\u5168\u5c40\u67e5\u8be2\u8fc7\u6ee4\u5668\u5b9e\u73b0\u63a5\u53e3\uff0c\u6240\u4ee5\u6211\u4eec\u9700\u8981\u914d\u7f6e\u5b9e\u4f53 ",Object(r.b)("inlineCode",{parentName:"p"},"TenantId")," \u8fc7\u6ee4\u5668"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{9,20-23}","{9,20-23}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class FurDbContext : AppDbContext, IMultiTenantOnTable, IModelBuilderFilter\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public Guid? GetTenantId()\n {\n return base.Tenant.TenantId;\n }\n\n public void OnCreating(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.HasQueryFilter(TenantIdQueryFilterExpression(entityBuilder, GetTenantId().Value));\n }\n }\n}\n')),Object(r.b)("h3",{id:"1057-\u91cd\u5199-savingchangesevent-\u4e8b\u4ef6\u65b9\u6cd5"},"10.5.7 \u91cd\u5199 ",Object(r.b)("inlineCode",{parentName:"h3"},"SavingChangesEvent")," \u4e8b\u4ef6\u65b9\u6cd5"),Object(r.b)("p",null,"\u901a\u8fc7\u4e0a\u9762\u7684\u6b65\u9aa4\uff0c\u6211\u4eec\u5df2\u7ecf\u89e3\u51b3\u4e86 ",Object(r.b)("inlineCode",{parentName:"p"},"\u67e5\u8be2")," \u79df\u6237\u8fc7\u6ee4\u529f\u80fd\uff0c\u4f46\u662f ",Object(r.b)("inlineCode",{parentName:"p"},"\u65b0\u589e")," \u548c ",Object(r.b)("inlineCode",{parentName:"p"},"\u66f4\u65b0")," \u8fd8\u672a\u5904\u7406\u3002"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"\u65b0\u589e")," \u6570\u636e\u7684\u65f6\u5019\u81ea\u52a8\u8bbe\u7f6e ",Object(r.b)("inlineCode",{parentName:"li"},"TenantId")," \u7684\u503c"),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"\u66f4\u65b0")," \u6570\u636e\u7684\u65f6\u5019\u6392\u9664 ",Object(r.b)("inlineCode",{parentName:"li"},"TenantId")," \u5c5e\u6027\u66f4\u65b0")),Object(r.b)("p",null,"\u5b9e\u73b0\u4e0a\u9762\u7684\u6b65\u9aa4\u5f88\u7b80\u5355\uff0c\u53ea\u9700\u8981\u91cd\u5199 ",Object(r.b)("inlineCode",{parentName:"p"},"SavingChangesEvent")," \u4e8b\u4ef6\u65b9\u6cd5\u5373\u53ef\u3002"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{26-48}","{26-48}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\nusing System.Linq;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class FurDbContext : AppDbContext, IMultiTenantOnTable, IModelBuilderFilter\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public Guid? GetTenantId()\n {\n return base.Tenant.TenantId;\n }\n\n public void OnCreating(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.HasQueryFilter(TenantIdQueryFilterExpression(entityBuilder, GetTenantId().Value));\n }\n\n protected override void SavingChangesEvent(object sender, SavingChangesEventArgs e)\n {\n // \u83b7\u53d6\u5f53\u524d\u4e8b\u4ef6\u5bf9\u5e94\u4e0a\u4e0b\u6587\n var dbContext = sender as FurDbContext;\n\n // \u83b7\u53d6\u6240\u6709\u65b0\u589e\u548c\u66f4\u65b0\u7684\u5b9e\u4f53\n var entities = dbContext.ChangeTracker.Entries().Where(u => u.State == EntityState.Added || u.State == EntityState.Modified);\n\n foreach (var entity in entities)\n {\n switch (entity.State)\n {\n // \u81ea\u52a8\u8bbe\u7f6e\u79df\u6237Id\n case EntityState.Added:\n entity.Property(nameof(Entity.TenantId)).CurrentValue = base.TenantId;\n break;\n // \u6392\u9664\u79df\u6237Id\n case EntityState.Modified:\n entity.Property(nameof(Entity.TenantId)).IsModified = false;\n break;\n }\n }\n }\n }\n}\n')),Object(r.b)("img",{src:Object(o.a)("img/saas1.png")}),Object(r.b)("h2",{id:"106-\u57fa\u4e8e-database-\u7684\u65b9\u5f0f"},"10.6 \u57fa\u4e8e ",Object(r.b)("inlineCode",{parentName:"h2"},"Database")," \u7684\u65b9\u5f0f"),Object(r.b)("p",null,"\u6b64\u65b9\u5f0f\u5728\u4e2d\u5927\u578b\u4f01\u4e1a\u7cfb\u7edf\u4e2d\u6700\u4e3a\u5e38\u7528\uff0c\u4e00\u4e2a\u79df\u6237\uff08\u5ba2\u6237\uff09\u4e00\u4e2a\u72ec\u7acb\u7684\u6570\u636e\u5e93\u3002"),Object(r.b)("h3",{id:"1061-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.6.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{6-7} title="Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"',"{6-7}":!0,title:'"Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class MultiTenantDbContext : AppDbContext\n {\n public MultiTenantDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-important alert alert--info"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u591a\u79df\u6237\u64cd\u4f5c\u5efa\u8bae\u5355\u72ec\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u800c\u4e14\u9700\u6307\u5b9a ",Object(r.b)("inlineCode",{parentName:"p"},"MultiTenantDbContextLocator")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u3002"))),Object(r.b)("h3",{id:"1062-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.6.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{13,14}","{13,14}":!0}),"using Fur.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.EntityFramework.Core\n{\n [Startup(600)]\n public sealed class FurEntityFrameworkCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddDatabaseAccessor(options =>\n {\n options.AddDb(DbProvider.Sqlite);\n options.AddDbPool(DbProvider.Sqlite);\n });\n }\n }\n}\n")),Object(r.b)("div",{className:"admonition admonition-caution alert alert--warning"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 16 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u9700\u8981 ",Object(r.b)("inlineCode",{parentName:"p"},"Database")," \u591a\u79df\u6237\u65b9\u6848\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u9700\u8981\u91c7\u7528 ",Object(r.b)("inlineCode",{parentName:"p"},"AddDb")," \u6ce8\u518c\uff0c\u800c\u4e0d\u662f ",Object(r.b)("inlineCode",{parentName:"p"},"AddDbPool"),"\u3002\u539f\u56e0\u662f ",Object(r.b)("inlineCode",{parentName:"p"},"AddDbPool")," \u65b9\u5f0f\u6ce8\u518c\u540e\u7eed\u4e0d\u652f\u6301 ",Object(r.b)("inlineCode",{parentName:"p"},"OnConfiguring")," \u91cd\u5199\uff01\uff01\uff01"))),Object(r.b)("h3",{id:"1063-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e"},"10.6.3 \u6dfb\u52a0 ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u79cd\u5b50\u6570\u636e"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{8,12-30} title="Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"',"{8,12-30}":!0,title:'"Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Fur.EntityFramework.Core\n{\n public class TenantSeedData : IEntitySeedData\n {\n public IEnumerable HasData(DbContext dbContext, Type dbContextLocator)\n {\n return new List\n {\n new Tenant\n {\n TenantId=Guid.Parse("383AFB88-F519-FFF8-B364-6D563BF3687F"),\n Name="\u9ed8\u8ba4\u79df\u6237",\n Host="localhost:44313",\n CreatedTime=DateTime.Parse("2020-10-06 20:19:07"),\n ConnectionString="Data Source=./Fur.db" // \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32\n },\n new Tenant\n {\n TenantId=Guid.Parse("C5798CB6-16D6-0F42-EB56-59C695353BC0"),\n Name="\u5176\u4ed6\u79df\u6237",\n Host="localhost:5000",\n CreatedTime=DateTime.Parse("2020-10-06 20:20:32"),\n ConnectionString="Data Source=./Fur2.db" // \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32\n }\n };\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u8bf4\u660e")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u8be5\u6b65\u9aa4\u53ea\u5728 ",Object(r.b)("inlineCode",{parentName:"p"},"Code First")," \u65b9\u5f0f\u6267\u884c\uff0c",Object(r.b)("inlineCode",{parentName:"p"},"Database First")," \u65e0\u9700\u914d\u7f6e\u79cd\u5b50\u6570\u636e\u3002"))),Object(r.b)("h3",{id:"1064-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868"},"10.6.4 \u6839\u636e\u6a21\u578b\u521b\u5efa ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u8868"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Add-Migration add_tenant_table -Context MultiTenantDbContext\n")),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Update-Database -Context MultiTenantDbContext\n")),Object(r.b)("h3",{id:"1065-\u5b9e\u73b0-imultitenantondatabase-\u63a5\u53e3"},"10.6.5 \u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"h3"},"IMultiTenantOnDatabase")," \u63a5\u53e3"),Object(r.b)("p",null,"\u5728\u9700\u8981\u591a\u79df\u6237\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"p"},"IMultiTenantOnDatabase")," \u63a5\u53e3\uff0c\u5982\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{6,12-15}","{6,12-15}":!0}),"using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n public class FurDbContext : AppDbContext, IMultiTenantOnDatabase\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public string GetDatabaseConnectionString()\n {\n return base.Tenant.ConnectionString;\n }\n }\n}\n")),Object(r.b)("h3",{id:"1066-\u91cd\u5199-onconfiguring-\u65b9\u6cd5"},"10.6.6 \u91cd\u5199 ",Object(r.b)("inlineCode",{parentName:"h3"},"OnConfiguring")," \u65b9\u6cd5"),Object(r.b)("p",null,"\u5728\u9700\u8981\u591a\u79df\u6237\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u91cd\u5199 ",Object(r.b)("inlineCode",{parentName:"p"},"OnConfiguring")," \u65b9\u6cd5\u5e76\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{12-17}","{12-17}":!0}),"using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n public class FurDbContext : AppDbContext, IMultiTenantOnDatabase\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)\n {\n optionsBuilder.UseSqlite(GetDatabaseConnectionString());\n\n base.OnConfiguring(optionsBuilder);\n }\n\n public string GetDatabaseConnectionString()\n {\n return base.Tenant.ConnectionString;\n }\n }\n}\n")),Object(r.b)("img",{src:Object(o.a)("img/saas2.png")}),Object(r.b)("h2",{id:"107-\u57fa\u4e8e-schema-\u7684\u65b9\u5f0f"},"10.7 \u57fa\u4e8e ",Object(r.b)("inlineCode",{parentName:"h2"},"Schema")," \u7684\u65b9\u5f0f"),Object(r.b)("p",null,"\u6b64\u65b9\u5f0f\u5728\u4e2d\u5c0f\u578b\u4f01\u4e1a\u7cfb\u7edf\u4e2d\u4e5f\u4e0d\u5c11\u89c1\uff0c\u4e00\u4e2a\u79df\u6237\uff08\u5ba2\u6237\uff09\u5171\u4eab\u6570\u636e\u5e93\u4e14\u4e0d\u540c ",Object(r.b)("inlineCode",{parentName:"p"},"Schema"),"\u3002"),Object(r.b)("h3",{id:"1071-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.7.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{6-7} title="Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"',"{6-7}":!0,title:'"Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class MultiTenantDbContext : AppDbContext\n {\n public MultiTenantDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-important alert alert--info"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u591a\u79df\u6237\u64cd\u4f5c\u5efa\u8bae\u5355\u72ec\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u800c\u4e14\u9700\u6307\u5b9a ",Object(r.b)("inlineCode",{parentName:"p"},"MultiTenantDbContextLocator")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u3002"))),Object(r.b)("h3",{id:"1072-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.7.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{14}","{14}":!0}),"using Fur.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.EntityFramework.Core\n{\n [Startup(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 options.AddDbPool(DbProvider.Sqlite);\n });\n }\n }\n}\n")),Object(r.b)("h3",{id:"1073-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e"},"10.7.3 \u6dfb\u52a0 ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u79cd\u5b50\u6570\u636e"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{8,12-30} title="Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"',"{8,12-30}":!0,title:'"Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Fur.EntityFramework.Core\n{\n public class TenantSeedData : IEntitySeedData\n {\n public IEnumerable HasData(DbContext dbContext, Type dbContextLocator)\n {\n return new List\n {\n new Tenant\n {\n TenantId=Guid.Parse("383AFB88-F519-FFF8-B364-6D563BF3687F"),\n Name="\u9ed8\u8ba4\u79df\u6237",\n Host="localhost:44313",\n CreatedTime=DateTime.Parse("2020-10-06 20:19:07"),\n Schema="dbo" // Schema\n },\n new Tenant\n {\n TenantId=Guid.Parse("C5798CB6-16D6-0F42-EB56-59C695353BC0"),\n Name="\u5176\u4ed6\u79df\u6237",\n Host="localhost:5000",\n CreatedTime=DateTime.Parse("2020-10-06 20:20:32"),\n Schema="fur" // Schema\n }\n };\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u8bf4\u660e")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u8be5\u6b65\u9aa4\u53ea\u5728 ",Object(r.b)("inlineCode",{parentName:"p"},"Code First")," \u65b9\u5f0f\u6267\u884c\uff0c",Object(r.b)("inlineCode",{parentName:"p"},"Database First")," \u65e0\u9700\u914d\u7f6e\u79cd\u5b50\u6570\u636e\u3002"))),Object(r.b)("h3",{id:"1074-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868"},"10.7.4 \u6839\u636e\u6a21\u578b\u521b\u5efa ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u8868"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Add-Migration add_tenant_table -Context MultiTenantDbContext\n")),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Update-Database -Context MultiTenantDbContext\n")),Object(r.b)("h3",{id:"1075-\u5b9e\u73b0-imultitenantonschema-\u63a5\u53e3"},"10.7.5 \u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"h3"},"IMultiTenantOnSchema")," \u63a5\u53e3"),Object(r.b)("p",null,"\u5728\u9700\u8981\u591a\u79df\u6237\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"p"},"IMultiTenantOnSchema")," \u63a5\u53e3\uff0c\u5982\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{6,12-15}","{6,12-15}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class FurDbContext : AppDbContext, IMultiTenantOnSchema\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public string GetSchemaName()\n {\n return base.Tenant.Schema;\n }\n }\n}\n')),Object(r.b)("h3",{id:"1076-\u5173\u4e8e-code-first-\u6570\u636e\u8fc1\u79fb"},"10.7.6 \u5173\u4e8e ",Object(r.b)("inlineCode",{parentName:"h3"},"Code First \u6570\u636e\u8fc1\u79fb")),Object(r.b)("p",null,"\u57fa\u4e8e ",Object(r.b)("inlineCode",{parentName:"p"},"Schema")," \u65b9\u5f0f\u6bd4\u8f83\u7279\u522b\uff0c\u751f\u6210\u6570\u636e\u8fc1\u79fb\u7684\u65f6\u5019\u6ca1\u529e\u6cd5\u83b7\u53d6\u79df\u6237\u4fe1\u606f\uff0c\u6240\u4ee5\u5efa\u8bae",Object(r.b)("strong",{parentName:"p"},"\u5206\u5f00\u591a\u6b21\u8fc1\u79fb"),"\uff0c\u5982\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),'public string GetSchemaName()\n{\n return base.Tenant.Schema?? "\u79df\u6237\u4e00Schema";\n}\n')),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),'public string GetSchemaName()\n{\n return base.Tenant.Schema?? "\u79df\u6237\u4e8cSchema";\n}\n')),Object(r.b)("p",null,"\u8fd9\u6837\u5c31\u53ef\u4ee5\u5728\u8fc1\u79fb\u7684\u65f6\u5019\u751f\u6210\u591a\u6b21\u8fc1\u79fb\u4e86\u3002"),Object(r.b)("h2",{id:"108-\u53cd\u9988\u4e0e\u5efa\u8bae"},"10.8 \u53cd\u9988\u4e0e\u5efa\u8bae"),Object(r.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e0e\u6211\u4eec\u4ea4\u6d41")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u7ed9 Fur \u63d0 ",Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://gitee.com/monksoul/Fur/issues/new?issue"}),"Issue"),"\u3002"))))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/1ea356f4.d84c9503.js b/docs/1ea356f4.d84c9503.js new file mode 100644 index 00000000000..58d064a7e5e --- /dev/null +++ b/docs/1ea356f4.d84c9503.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[14],{138:function(e,n,t){"use strict";t.d(n,"a",(function(){return d})),t.d(n,"b",(function(){return m}));var a=t(0),i=t.n(a);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 c(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 s=i.a.createContext({}),l=function(e){var n=i.a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):c(c({},n),e)),t},d=function(e){var n=l(e.components);return i.a.createElement(s.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return i.a.createElement(i.a.Fragment,{},n)}},u=i.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,r=e.originalType,o=e.parentName,s=b(e,["components","mdxType","originalType","parentName"]),d=l(t),u=a,m=d["".concat(o,".").concat(u)]||d[u]||p[u]||r;return t?i.a.createElement(m,c(c({ref:n},s),{},{components:t})):i.a.createElement(m,c({ref:n},s))}));function m(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var r=t.length,o=new Array(r);o[0]=u;var c={};for(var b in n)hasOwnProperty.call(n,b)&&(c[b]=n[b]);c.originalType=e,c.mdxType="string"==typeof e?e:a,o[1]=c;for(var s=2;sfunction(e,n,t,{forcePrependBaseUrl:a=!1,absolute:r=!1}={}){if(!t)return t;if(t.startsWith("#"))return t;if(Object(i.b)(t))return t;if(a)return n+t;const o=t.startsWith(n)?t:n+t.replace(/^\//,"");return r?e+o:o}(n,e,t,a)}}function o(e,n={}){const{withBaseUrl:t}=r();return t(e,n)}},141:function(e,n,t){"use strict";function a(e){return!0===/^(\w*:|\/\/)/.test(e)}function i(e){return void 0!==e&&!a(e)}t.d(n,"b",(function(){return a})),t.d(n,"a",(function(){return i}))},69:function(e,n,t){"use strict";t.r(n),t.d(n,"frontMatter",(function(){return c})),t.d(n,"metadata",(function(){return b})),t.d(n,"rightToc",(function(){return s})),t.d(n,"default",(function(){return d}));var a=t(2),i=t(6),r=(t(0),t(138)),o=t(140),c={id:"saas",title:"10. SaaS \u591a\u79df\u6237",sidebar_label:"10. SaaS \u591a\u79df\u6237"},b={unversionedId:"saas",id:"saas",isDocsHomePage:!1,title:"10. SaaS \u591a\u79df\u6237",description:"10.1 \u4ec0\u4e48\u662f SaaS",source:"@site/docs\\saas.mdx",slug:"/saas",permalink:"/docs/saas",editUrl:"https://gitee.com/monksoul/Fur/tree/main/handbook/docs/saas.mdx",version:"current",sidebar_label:"10. SaaS \u591a\u79df\u6237",sidebar:"docs",previous:{title:"9.27 \u5206\u8868\u5206\u5e93",permalink:"/docs/split-db"},next:{title:"11. \u4f9d\u8d56\u6ce8\u5165/\u63a7\u5236\u53cd\u8f6c",permalink:"/docs/dependency-injection"}},s=[{value:"10.1 \u4ec0\u4e48\u662f SaaS",id:"101-\u4ec0\u4e48\u662f-saas",children:[]},{value:"10.2 \u4ec0\u4e48\u662f\u591a\u79df\u6237",id:"102-\u4ec0\u4e48\u662f\u591a\u79df\u6237",children:[]},{value:"10.3 \u5b9e\u73b0\u591a\u79df\u6237\u65b9\u6848",id:"103-\u5b9e\u73b0\u591a\u79df\u6237\u65b9\u6848",children:[{value:"10.3.1 \u72ec\u7acb\u6570\u636e\u5e93",id:"1031-\u72ec\u7acb\u6570\u636e\u5e93",children:[]},{value:"10.3.2 \u5171\u4eab\u6570\u636e\u5e93\uff0c\u72ec\u7acb Schema",id:"1032-\u5171\u4eab\u6570\u636e\u5e93\uff0c\u72ec\u7acb-schema",children:[]},{value:"10.3.3 \u5171\u4eab\u6570\u636e\u5e93\uff0c\u5171\u4eab Schema",id:"1033-\u5171\u4eab\u6570\u636e\u5e93\uff0c\u5171\u4eab-schema",children:[]}]},{value:"10.4 \u591a\u79df\u6237\u4f7f\u7528\u65b9\u6848",id:"104-\u591a\u79df\u6237\u4f7f\u7528\u65b9\u6848",children:[]},{value:"10.5 \u57fa\u4e8e TenantId \u7684\u65b9\u5f0f",id:"105-\u57fa\u4e8e-tenantid-\u7684\u65b9\u5f0f",children:[{value:"10.5.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1051-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.5.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1052-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.5.3 \u6dfb\u52a0 Tenant \u79cd\u5b50\u6570\u636e",id:"1053-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e",children:[]},{value:"10.5.4 \u6839\u636e\u6a21\u578b\u521b\u5efa Tenant \u8868",id:"1054-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868",children:[]},{value:"10.5.5 \u5b9e\u73b0 IMultiTenantOnTable \u63a5\u53e3",id:"1055-\u5b9e\u73b0-imultitenantontable-\u63a5\u53e3",children:[]},{value:"10.5.6 \u5b9e\u73b0 IModelBuilderFilter \u63a5\u53e3",id:"1056-\u5b9e\u73b0-imodelbuilderfilter-\u63a5\u53e3",children:[]},{value:"10.5.7 \u91cd\u5199 SavingChangesEvent \u4e8b\u4ef6\u65b9\u6cd5",id:"1057-\u91cd\u5199-savingchangesevent-\u4e8b\u4ef6\u65b9\u6cd5",children:[]}]},{value:"10.6 \u57fa\u4e8e Database \u7684\u65b9\u5f0f",id:"106-\u57fa\u4e8e-database-\u7684\u65b9\u5f0f",children:[{value:"10.6.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1061-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.6.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1062-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.6.3 \u6dfb\u52a0 Tenant \u79cd\u5b50\u6570\u636e",id:"1063-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e",children:[]},{value:"10.6.4 \u6839\u636e\u6a21\u578b\u521b\u5efa Tenant \u8868",id:"1064-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868",children:[]},{value:"10.6.5 \u5b9e\u73b0 IMultiTenantOnDatabase \u63a5\u53e3",id:"1065-\u5b9e\u73b0-imultitenantondatabase-\u63a5\u53e3",children:[]},{value:"10.6.6 \u91cd\u5199 OnConfiguring \u65b9\u6cd5",id:"1066-\u91cd\u5199-onconfiguring-\u65b9\u6cd5",children:[]}]},{value:"10.7 \u57fa\u4e8e Schema \u7684\u65b9\u5f0f",id:"107-\u57fa\u4e8e-schema-\u7684\u65b9\u5f0f",children:[{value:"10.7.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1071-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.7.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1072-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.7.3 \u6dfb\u52a0 Tenant \u79cd\u5b50\u6570\u636e",id:"1073-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e",children:[]},{value:"10.7.4 \u6839\u636e\u6a21\u578b\u521b\u5efa Tenant \u8868",id:"1074-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868",children:[]},{value:"10.7.5 \u5b9e\u73b0 IMultiTenantOnSchema \u63a5\u53e3",id:"1075-\u5b9e\u73b0-imultitenantonschema-\u63a5\u53e3",children:[]},{value:"10.7.6 \u5173\u4e8e Code First \u6570\u636e\u8fc1\u79fb",id:"1076-\u5173\u4e8e-code-first-\u6570\u636e\u8fc1\u79fb",children:[]}]},{value:"10.8 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"108-\u53cd\u9988\u4e0e\u5efa\u8bae",children:[]}],l={rightToc:s};function d(e){var n=e.components,t=Object(i.a)(e,["components"]);return Object(r.b)("wrapper",Object(a.a)({},l,t,{components:n,mdxType:"MDXLayout"}),Object(r.b)("h2",{id:"101-\u4ec0\u4e48\u662f-saas"},"10.1 \u4ec0\u4e48\u662f ",Object(r.b)("inlineCode",{parentName:"h2"},"SaaS")),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"SaaS \u662f Software-as-a-Service\uff08\u8f6f\u4ef6\u5373\u670d\u52a1\uff09\u7684\u7b80\u79f0\uff0c\u968f\u7740\u4e92\u8054\u7f51\u6280\u672f\u7684\u53d1\u5c55\u548c\u5e94\u7528\u8f6f\u4ef6\u7684\u6210\u719f\uff0c \u5728 21 \u4e16\u7eaa\u5f00\u59cb\u5174\u8d77\u7684\u4e00\u79cd\u5b8c\u5168\u521b\u65b0\u7684\u8f6f\u4ef6\u5e94\u7528\u6a21\u5f0f\u3002\u5b83\u4e0e\u201con-demand software\u201d\uff0cthe application service provider(ASP\uff0c\u5e94\u7528\u670d\u52a1\u63d0\u4f9b\u5546)\uff0chosted software(\u6258\u7ba1\u8f6f\u4ef6)\u6240\u5177\u6709\u76f8\u4f3c\u7684\u542b\u4e49\u3002"),Object(r.b)("p",{parentName:"blockquote"},"\u5b83\u662f\u4e00\u79cd\u901a\u8fc7 Internet \u63d0\u4f9b\u8f6f\u4ef6\u7684\u6a21\u5f0f\uff0c\u5382\u5546\u5c06\u5e94\u7528\u8f6f\u4ef6\u7edf\u4e00\u90e8\u7f72\u5728\u81ea\u5df1\u7684\u670d\u52a1\u5668\u4e0a\uff0c\u5ba2\u6237\u53ef\u4ee5\u6839\u636e\u81ea\u5df1\u5b9e\u9645\u9700\u6c42\uff0c\u901a\u8fc7\u4e92\u8054\u7f51\u5411\u5382\u5546\u5b9a\u8d2d\u6240\u9700\u7684\u5e94\u7528\u8f6f\u4ef6\u670d\u52a1\uff0c\u6309\u5b9a\u8d2d\u7684\u670d\u52a1\u591a\u5c11\u548c\u65f6\u95f4\u957f\u77ed\u5411\u5382\u5546\u652f\u4ed8\u8d39\u7528\uff0c\u5e76\u901a\u8fc7\u4e92\u8054\u7f51\u83b7\u5f97\u5382\u5546\u63d0\u4f9b\u7684\u670d\u52a1\u3002\u7528\u6237\u4e0d\u7528\u518d\u8d2d\u4e70\u8f6f\u4ef6\uff0c\u800c\u6539\u7528\u5411\u63d0\u4f9b\u5546\u79df\u7528\u57fa\u4e8e Web \u7684\u8f6f\u4ef6\uff0c\u6765\u7ba1\u7406\u4f01\u4e1a\u7ecf\u8425\u6d3b\u52a8\uff0c\u4e14\u65e0\u9700\u5bf9\u8f6f\u4ef6\u8fdb\u884c\u7ef4\u62a4\uff0c\u670d\u52a1\u63d0\u4f9b\u5546\u4f1a\u5168\u6743\u7ba1\u7406\u548c\u7ef4\u62a4\u8f6f\u4ef6\uff0c\u8f6f\u4ef6\u5382\u5546\u5728\u5411\u5ba2\u6237\u63d0\u4f9b\u4e92\u8054\u7f51\u5e94\u7528\u7684\u540c\u65f6\uff0c\u4e5f\u63d0\u4f9b\u8f6f\u4ef6\u7684\u79bb\u7ebf\u64cd\u4f5c\u548c\u672c\u5730\u6570\u636e\u5b58\u50a8\uff0c\u8ba9\u7528\u6237\u968f\u65f6\u968f\u5730\u90fd\u53ef\u4ee5\u4f7f\u7528\u5176\u5b9a\u8d2d\u7684\u8f6f\u4ef6\u548c\u670d\u52a1\u3002"),Object(r.b)("p",{parentName:"blockquote"},"\u5bf9\u4e8e\u8bb8\u591a\u5c0f\u578b\u4f01\u4e1a\u6765\u8bf4\uff0cSaaS \u662f\u91c7\u7528\u5148\u8fdb\u6280\u672f\u7684\u6700\u597d\u9014\u5f84\uff0c\u5b83\u6d88\u9664\u4e86\u4f01\u4e1a\u8d2d\u4e70\u3001\u6784\u5efa\u548c\u7ef4\u62a4\u57fa\u7840\u8bbe\u65bd\u548c\u5e94\u7528\u7a0b\u5e8f\u7684\u9700\u8981\u3002")),Object(r.b)("h2",{id:"102-\u4ec0\u4e48\u662f\u591a\u79df\u6237"},"10.2 \u4ec0\u4e48\u662f\u591a\u79df\u6237"),Object(r.b)("p",null,"\u591a\u79df\u6237\u6280\u672f\u6216\u79f0\u591a\u91cd\u79df\u8d41\u6280\u672f\uff0c\u7b80\u79f0 ",Object(r.b)("inlineCode",{parentName:"p"},"SaaS"),"\uff0c\u662f\u4e00\u79cd\u8f6f\u4ef6\u67b6\u6784\u6280\u672f\uff0c\u662f\u5b9e\u73b0\u5982\u4f55\u5728\u591a\u7528\u6237\u73af\u5883\u4e0b\uff08\u6b64\u5904\u7684\u591a\u7528\u6237\u4e00\u822c\u662f\u9762\u5411\u4f01\u4e1a\u7528\u6237\uff09\u5171\u7528\u76f8\u540c\u7684\u7cfb\u7edf\u6216\u7a0b\u5e8f\u7ec4\u4ef6\uff0c\u5e76\u4e14\u53ef\u786e\u4fdd\u5404\u7528\u6237\u95f4\u6570\u636e\u7684\u9694\u79bb\u6027\u3002"),Object(r.b)("p",null,Object(r.b)("strong",{parentName:"p"},"\u7b80\u5355\u8bb2\uff1a\u5728\u4e00\u53f0\u670d\u52a1\u5668\u4e0a\u8fd0\u884c\u5355\u4e2a\u5e94\u7528\u5b9e\u4f8b\uff0c\u5b83\u4e3a\u591a\u4e2a\u79df\u6237\uff08\u5ba2\u6237\uff09\u63d0\u4f9b\u670d\u52a1\u3002"),"\u4ece\u5b9a\u4e49\u4e2d\u6211\u4eec\u53ef\u4ee5\u7406\u89e3\uff1a\u591a\u79df\u6237\u662f\u4e00\u79cd\u67b6\u6784\uff0c\u76ee\u7684\u662f\u4e3a\u4e86\u8ba9\u591a\u7528\u6237\u73af\u5883\u4e0b\u4f7f\u7528\u540c\u4e00\u5957\u7a0b\u5e8f\uff0c\u4e14\u4fdd\u8bc1\u7528\u6237\u95f4\u6570\u636e\u9694\u79bb\u3002\u90a3\u4e48\u91cd\u70b9\u5c31\u5f88\u6d45\u663e\u6613\u61c2\u4e86\uff0c\u591a\u79df\u6237\u7684\u91cd\u70b9\u5c31\u662f\u540c\u4e00\u5957\u7a0b\u5e8f\u4e0b\u5b9e\u73b0\u591a\u7528\u6237\u6570\u636e\u7684\u9694\u79bb\u3002"),Object(r.b)("h2",{id:"103-\u5b9e\u73b0\u591a\u79df\u6237\u65b9\u6848"},"10.3 \u5b9e\u73b0\u591a\u79df\u6237\u65b9\u6848"),Object(r.b)("h3",{id:"1031-\u72ec\u7acb\u6570\u636e\u5e93"},"10.3.1 \u72ec\u7acb\u6570\u636e\u5e93"),Object(r.b)("p",null,"\u8fd9\u662f\u7b2c\u4e00\u79cd\u65b9\u6848\uff0c\u5373\u4e00\u4e2a\u79df\u6237\u4e00\u4e2a\u6570\u636e\u5e93\uff0c\u8fd9\u79cd\u65b9\u6848\u7684\u7528\u6237\u6570\u636e\u9694\u79bb\u7ea7\u522b\u6700\u9ad8\uff0c\u5b89\u5168\u6027\u6700\u597d\uff0c\u4f46\u6210\u672c\u8f83\u9ad8\u3002"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u4f18\u70b9\uff1a"),"\n\u4e3a\u4e0d\u540c\u7684\u79df\u6237\u63d0\u4f9b\u72ec\u7acb\u7684\u6570\u636e\u5e93\uff0c\u6709\u52a9\u4e8e\u7b80\u5316\u6570\u636e\u6a21\u578b\u7684\u6269\u5c55\u8bbe\u8ba1\uff0c\u6ee1\u8db3\u4e0d\u540c\u79df\u6237\u7684\u72ec\u7279\u9700\u6c42\uff1b\u5982\u679c\u51fa\u73b0\u6545\u969c\uff0c\u6062\u590d\u6570\u636e\u6bd4\u8f83\u7b80\u5355\u3002")),Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u7f3a\u70b9\uff1a"),"\n\u589e\u591a\u4e86\u6570\u636e\u5e93\u7684\u5b89\u88c5\u6570\u91cf\uff0c\u968f\u4e4b\u5e26\u6765\u7ef4\u62a4\u6210\u672c\u548c\u8d2d\u7f6e\u6210\u672c\u7684\u589e\u52a0\u3002 \u8fd9\u79cd\u65b9\u6848\u4e0e\u4f20\u7edf\u7684\u4e00\u4e2a\u5ba2\u6237\u3001\u4e00\u5957\u6570\u636e\u3001\u4e00\u5957\u90e8\u7f72\u7c7b\u4f3c\uff0c\u5dee\u522b\u53ea\u5728\u4e8e\u8f6f\u4ef6\u7edf\u4e00\u90e8\u7f72\u5728\u8fd0\u8425\u5546\u90a3\u91cc\u3002\u5982\u679c\u9762\u5bf9\u7684\u662f\u94f6\u884c\u3001\u533b\u9662\u7b49\u9700\u8981\u975e\u5e38\u9ad8\u6570\u636e\u9694\u79bb\u7ea7\u522b\u7684\u79df\u6237\uff0c\u53ef\u4ee5\u9009\u62e9\u8fd9\u79cd\u6a21\u5f0f\uff0c\u63d0\u9ad8\u79df\u7528\u7684\u5b9a\u4ef7\u3002\u5982\u679c\u5b9a\u4ef7\u8f83\u4f4e\uff0c\u4ea7\u54c1\u8d70\u4f4e\u4ef7\u8def\u7ebf\uff0c\u8fd9\u79cd\u65b9\u6848\u4e00\u822c\u5bf9\u8fd0\u8425\u5546\u6765\u8bf4\u662f\u65e0\u6cd5\u627f\u53d7\u7684\u3002"))),Object(r.b)("h3",{id:"1032-\u5171\u4eab\u6570\u636e\u5e93\uff0c\u72ec\u7acb-schema"},"10.3.2 \u5171\u4eab\u6570\u636e\u5e93\uff0c\u72ec\u7acb ",Object(r.b)("inlineCode",{parentName:"h3"},"Schema")),Object(r.b)("p",null,"\u8fd9\u662f\u7b2c\u4e8c\u79cd\u65b9\u6848\uff0c\u5373\u591a\u4e2a\u6216\u6240\u6709\u79df\u6237\u5171\u4eab ",Object(r.b)("inlineCode",{parentName:"p"},"Database"),"\uff0c\u4f46\u662f\u6bcf\u4e2a\u79df\u6237\u4e00\u4e2a ",Object(r.b)("inlineCode",{parentName:"p"},"Schema"),"\uff08\u4e5f\u53ef\u53eb\u505a\u4e00\u4e2a user\uff09\u3002\u5e95\u5c42\u5e93\u6bd4\u5982\u662f\uff1a",Object(r.b)("inlineCode",{parentName:"p"},"SqlServer"),"\u3001",Object(r.b)("inlineCode",{parentName:"p"},"Oracle")," \u7b49\uff0c\u4e00\u4e2a\u6570\u636e\u5e93\u4e0b\u53ef\u4ee5\u6709\u591a\u4e2a ",Object(r.b)("inlineCode",{parentName:"p"},"Schema"),"\u3002"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u4f18\u70b9\uff1a"),"\n\u4e3a\u5b89\u5168\u6027\u8981\u6c42\u8f83\u9ad8\u7684\u79df\u6237\u63d0\u4f9b\u4e86\u4e00\u5b9a\u7a0b\u5ea6\u7684\u903b\u8f91\u6570\u636e\u9694\u79bb\uff0c\u5e76\u4e0d\u662f\u5b8c\u5168\u9694\u79bb\uff1b\u6bcf\u4e2a\u6570\u636e\u5e93\u53ef\u652f\u6301\u66f4\u591a\u7684\u79df\u6237\u6570\u91cf\u3002")),Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u7f3a\u70b9\uff1a"),"\n\u5982\u679c\u51fa\u73b0\u6545\u969c\uff0c\u6570\u636e\u6062\u590d\u6bd4\u8f83\u56f0\u96be\uff0c\u56e0\u4e3a\u6062\u590d\u6570\u636e\u5e93\u5c06\u7275\u6d89\u5230\u5176\u4ed6\u79df\u6237\u7684\u6570\u636e\uff1b \u5982\u679c\u9700\u8981\u8de8\u79df\u6237\u7edf\u8ba1\u6570\u636e\uff0c\u5b58\u5728\u4e00\u5b9a\u56f0\u96be\u3002"))),Object(r.b)("h3",{id:"1033-\u5171\u4eab\u6570\u636e\u5e93\uff0c\u5171\u4eab-schema"},"10.3.3 \u5171\u4eab\u6570\u636e\u5e93\uff0c\u5171\u4eab ",Object(r.b)("inlineCode",{parentName:"h3"},"Schema")),Object(r.b)("p",null,"\u5171\u4eab\u6570\u636e\u8868 \u8fd9\u662f\u7b2c\u4e09\u79cd\u65b9\u6848\uff0c\u5373\u79df\u6237\u5171\u4eab\u540c\u4e00\u4e2a ",Object(r.b)("inlineCode",{parentName:"p"},"Database"),"\u3001\u540c\u4e00\u4e2a ",Object(r.b)("inlineCode",{parentName:"p"},"Schema"),"\uff0c\u4f46\u5728\u8868\u4e2d\u589e\u52a0 ",Object(r.b)("strong",{parentName:"p"},Object(r.b)("inlineCode",{parentName:"strong"},"TenantId"))," \u591a\u79df\u6237\u7684\u6570\u636e\u5b57\u6bb5\u3002\u8fd9\u662f\u5171\u4eab\u7a0b\u5ea6\u6700\u9ad8\u3001\u9694\u79bb\u7ea7\u522b\u6700\u4f4e\u7684\u6a21\u5f0f\u3002 \u5373\u6bcf\u63d2\u5165\u4e00\u6761\u6570\u636e\u65f6\u90fd\u9700\u8981\u6709\u4e00\u4e2a\u5ba2\u6237\u7684\u6807\u8bc6\u3002\u8fd9\u6837\u624d\u80fd\u5728\u540c\u4e00\u5f20\u8868\u4e2d\u533a\u5206\u51fa\u4e0d\u540c\u5ba2\u6237\u7684\u6570\u636e\u3002"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u4f18\u70b9\uff1a"),"\n\u4e09\u79cd\u65b9\u6848\u6bd4\u8f83\uff0c\u7b2c\u4e09\u79cd\u65b9\u6848\u7684\u7ef4\u62a4\u548c\u8d2d\u7f6e\u6210\u672c\u6700\u4f4e\uff0c\u5141\u8bb8\u6bcf\u4e2a\u6570\u636e\u5e93\u652f\u6301\u7684\u79df\u6237\u6570\u91cf\u6700\u591a\u3002")),Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u7f3a\u70b9\uff1a"),"\n\u9694\u79bb\u7ea7\u522b\u6700\u4f4e\uff0c\u5b89\u5168\u6027\u6700\u4f4e\uff0c\u9700\u8981\u5728\u8bbe\u8ba1\u5f00\u53d1\u65f6\u52a0\u5927\u5bf9\u5b89\u5168\u7684\u5f00\u53d1\u91cf\uff1b \u6570\u636e\u5907\u4efd\u548c\u6062\u590d\u6700\u56f0\u96be\uff0c\u9700\u8981\u9010\u8868\u9010\u6761\u5907\u4efd\u548c\u8fd8\u539f\u3002"))),Object(r.b)("h2",{id:"104-\u591a\u79df\u6237\u4f7f\u7528\u65b9\u6848"},"10.4 \u591a\u79df\u6237\u4f7f\u7528\u65b9\u6848"),Object(r.b)("p",null,Object(r.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u652f\u6301\u4ee5\u4e0a\u4e09\u79cd\u591a\u79df\u6237\u5b9e\u73b0\u65b9\u6848\uff0c\u4f7f\u7528\u7b80\u5355\u4e14\u5bb9\u6613\u7ef4\u62a4\u3002\u4e0b\u9762\u5206\u522b\u4f7f\u7528\u4e09\u79cd\u4e0d\u540c\u65b9\u5f0f\u6f14\u793a\u591a\u79df\u6237\u65b9\u6848\u7528\u6cd5\u3002"),Object(r.b)("h2",{id:"105-\u57fa\u4e8e-tenantid-\u7684\u65b9\u5f0f"},"10.5 \u57fa\u4e8e ",Object(r.b)("inlineCode",{parentName:"h2"},"TenantId")," \u7684\u65b9\u5f0f"),Object(r.b)("p",null,"\u6b64\u65b9\u5f0f\u5728\u4e2d\u5c0f\u578b\u4f01\u4e1a\u7cfb\u7edf\u4e2d\u6700\u4e3a\u5e38\u7528\uff0c\u7ef4\u62a4\u6210\u672c\u4f4e\uff0c\u8d2d\u7f6e\u6210\u672c\u4f4e\u3002"),Object(r.b)("h3",{id:"1051-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.5.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{6-7} title="Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"',"{6-7}":!0,title:'"Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class MultiTenantDbContext : AppDbContext\n {\n public MultiTenantDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-important alert alert--info"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u591a\u79df\u6237\u64cd\u4f5c\u5efa\u8bae\u5355\u72ec\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u800c\u4e14\u9700\u6307\u5b9a ",Object(r.b)("inlineCode",{parentName:"p"},"MultiTenantDbContextLocator")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u3002"))),Object(r.b)("h3",{id:"1052-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.5.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{14}","{14}":!0}),"using Fur.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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 options.AddDbPool(DbProvider.Sqlite);\n });\n }\n }\n}\n")),Object(r.b)("h3",{id:"1053-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e"},"10.5.3 \u6dfb\u52a0 ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u79cd\u5b50\u6570\u636e"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{8,12-28} title="Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"',"{8,12-28}":!0,title:'"Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Fur.EntityFramework.Core\n{\n public class TenantSeedData : IEntitySeedData\n {\n public IEnumerable HasData(DbContext dbContext, Type dbContextLocator)\n {\n return new List\n {\n new Tenant\n {\n TenantId=Guid.Parse("383AFB88-F519-FFF8-B364-6D563BF3687F"),\n Name="\u9ed8\u8ba4\u79df\u6237",\n Host="localhost:44313",\n CreatedTime=DateTime.Parse("2020-10-06 20:19:07")\n },\n new Tenant\n {\n TenantId=Guid.Parse("C5798CB6-16D6-0F42-EB56-59C695353BC0"),\n Name="\u5176\u4ed6\u79df\u6237",\n Host="localhost:5000",\n CreatedTime=DateTime.Parse("2020-10-06 20:20:32")\n }\n };\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u8bf4\u660e")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u8be5\u6b65\u9aa4\u53ea\u5728 ",Object(r.b)("inlineCode",{parentName:"p"},"Code First")," \u65b9\u5f0f\u6267\u884c\uff0c",Object(r.b)("inlineCode",{parentName:"p"},"Database First")," \u65e0\u9700\u914d\u7f6e\u79cd\u5b50\u6570\u636e\u3002"))),Object(r.b)("h3",{id:"1054-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868"},"10.5.4 \u6839\u636e\u6a21\u578b\u521b\u5efa ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u8868"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Add-Migration add_tenant_table -Context MultiTenantDbContext\n")),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Update-Database -Context MultiTenantDbContext\n")),Object(r.b)("h3",{id:"1055-\u5b9e\u73b0-imultitenantontable-\u63a5\u53e3"},"10.5.5 \u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"h3"},"IMultiTenantOnTable")," \u63a5\u53e3"),Object(r.b)("p",null,"\u5728\u9700\u8981\u591a\u79df\u6237\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"p"},"IMultiTenantOnTable")," \u63a5\u53e3\uff0c\u5982\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{8,14-17}","{8,14-17}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing System;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class FurDbContext : AppDbContext, IMultiTenantOnTable, IModelBuilderFilter\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public Guid? GetTenantId()\n {\n return base.Tenant.TenantId;\n }\n }\n}\n')),Object(r.b)("p",null,"\u5728 ",Object(r.b)("inlineCode",{parentName:"p"},"GetTenantId()")," \u65b9\u6cd5\u4e2d\uff0c\u9996\u5148\u83b7\u53d6\u8bf7\u6c42\u7684 ",Object(r.b)("inlineCode",{parentName:"p"},"\u4e3b\u673a\u5730\u5740"),"\uff0c\u7136\u540e\u6839\u636e\u4e3b\u673a\u5730\u5740\u67e5\u8be2\u5bf9\u5e94\u7684\u79df\u6237 ",Object(r.b)("inlineCode",{parentName:"p"},"TenantIdId"),"\uff0c\u907f\u514d\u591a\u6b21\u67e5\u8be2\u6570\u636e\u5e93\uff0c\u8fd9\u91cc\u4f7f\u7528\u4e86 ",Object(r.b)("inlineCode",{parentName:"p"},"IMemoryCache")," \u5185\u5b58\u7f13\u5b58\u3002"),Object(r.b)("h3",{id:"1056-\u5b9e\u73b0-imodelbuilderfilter-\u63a5\u53e3"},"10.5.6 \u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"h3"},"IModelBuilderFilter")," \u63a5\u53e3"),Object(r.b)("p",null,Object(r.b)("inlineCode",{parentName:"p"},"IModelBuilderFilter")," \u63a5\u53e3\u662f\u5168\u5c40\u67e5\u8be2\u8fc7\u6ee4\u5668\u5b9e\u73b0\u63a5\u53e3\uff0c\u6240\u4ee5\u6211\u4eec\u9700\u8981\u914d\u7f6e\u5b9e\u4f53 ",Object(r.b)("inlineCode",{parentName:"p"},"TenantId")," \u8fc7\u6ee4\u5668"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{9,20-23}","{9,20-23}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class FurDbContext : AppDbContext, IMultiTenantOnTable, IModelBuilderFilter\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public Guid? GetTenantId()\n {\n return base.Tenant.TenantId;\n }\n\n public void OnCreating(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.HasQueryFilter(TenantIdQueryFilterExpression(entityBuilder, GetTenantId().Value));\n }\n }\n}\n')),Object(r.b)("h3",{id:"1057-\u91cd\u5199-savingchangesevent-\u4e8b\u4ef6\u65b9\u6cd5"},"10.5.7 \u91cd\u5199 ",Object(r.b)("inlineCode",{parentName:"h3"},"SavingChangesEvent")," \u4e8b\u4ef6\u65b9\u6cd5"),Object(r.b)("p",null,"\u901a\u8fc7\u4e0a\u9762\u7684\u6b65\u9aa4\uff0c\u6211\u4eec\u5df2\u7ecf\u89e3\u51b3\u4e86 ",Object(r.b)("inlineCode",{parentName:"p"},"\u67e5\u8be2")," \u79df\u6237\u8fc7\u6ee4\u529f\u80fd\uff0c\u4f46\u662f ",Object(r.b)("inlineCode",{parentName:"p"},"\u65b0\u589e")," \u548c ",Object(r.b)("inlineCode",{parentName:"p"},"\u66f4\u65b0")," \u8fd8\u672a\u5904\u7406\u3002"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"\u65b0\u589e")," \u6570\u636e\u7684\u65f6\u5019\u81ea\u52a8\u8bbe\u7f6e ",Object(r.b)("inlineCode",{parentName:"li"},"TenantId")," \u7684\u503c"),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"\u66f4\u65b0")," \u6570\u636e\u7684\u65f6\u5019\u6392\u9664 ",Object(r.b)("inlineCode",{parentName:"li"},"TenantId")," \u5c5e\u6027\u66f4\u65b0")),Object(r.b)("p",null,"\u5b9e\u73b0\u4e0a\u9762\u7684\u6b65\u9aa4\u5f88\u7b80\u5355\uff0c\u53ea\u9700\u8981\u91cd\u5199 ",Object(r.b)("inlineCode",{parentName:"p"},"SavingChangesEvent")," \u4e8b\u4ef6\u65b9\u6cd5\u5373\u53ef\u3002"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{26-48}","{26-48}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\nusing System.Linq;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class FurDbContext : AppDbContext, IMultiTenantOnTable, IModelBuilderFilter\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public Guid? GetTenantId()\n {\n return base.Tenant.TenantId;\n }\n\n public void OnCreating(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.HasQueryFilter(TenantIdQueryFilterExpression(entityBuilder, GetTenantId().Value));\n }\n\n protected override void SavingChangesEvent(object sender, SavingChangesEventArgs e)\n {\n // \u83b7\u53d6\u5f53\u524d\u4e8b\u4ef6\u5bf9\u5e94\u4e0a\u4e0b\u6587\n var dbContext = sender as FurDbContext;\n\n // \u83b7\u53d6\u6240\u6709\u65b0\u589e\u548c\u66f4\u65b0\u7684\u5b9e\u4f53\n var entities = dbContext.ChangeTracker.Entries().Where(u => u.State == EntityState.Added || u.State == EntityState.Modified);\n\n foreach (var entity in entities)\n {\n switch (entity.State)\n {\n // \u81ea\u52a8\u8bbe\u7f6e\u79df\u6237Id\n case EntityState.Added:\n entity.Property(nameof(Entity.TenantId)).CurrentValue = base.TenantId;\n break;\n // \u6392\u9664\u79df\u6237Id\n case EntityState.Modified:\n entity.Property(nameof(Entity.TenantId)).IsModified = false;\n break;\n }\n }\n }\n }\n}\n')),Object(r.b)("img",{src:Object(o.a)("img/saas1.png")}),Object(r.b)("h2",{id:"106-\u57fa\u4e8e-database-\u7684\u65b9\u5f0f"},"10.6 \u57fa\u4e8e ",Object(r.b)("inlineCode",{parentName:"h2"},"Database")," \u7684\u65b9\u5f0f"),Object(r.b)("p",null,"\u6b64\u65b9\u5f0f\u5728\u4e2d\u5927\u578b\u4f01\u4e1a\u7cfb\u7edf\u4e2d\u6700\u4e3a\u5e38\u7528\uff0c\u4e00\u4e2a\u79df\u6237\uff08\u5ba2\u6237\uff09\u4e00\u4e2a\u72ec\u7acb\u7684\u6570\u636e\u5e93\u3002"),Object(r.b)("h3",{id:"1061-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.6.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{6-7} title="Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"',"{6-7}":!0,title:'"Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class MultiTenantDbContext : AppDbContext\n {\n public MultiTenantDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-important alert alert--info"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u591a\u79df\u6237\u64cd\u4f5c\u5efa\u8bae\u5355\u72ec\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u800c\u4e14\u9700\u6307\u5b9a ",Object(r.b)("inlineCode",{parentName:"p"},"MultiTenantDbContextLocator")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u3002"))),Object(r.b)("h3",{id:"1062-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.6.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{13,14}","{13,14}":!0}),"using Fur.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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.AddDb(DbProvider.Sqlite);\n options.AddDbPool(DbProvider.Sqlite);\n });\n }\n }\n}\n")),Object(r.b)("div",{className:"admonition admonition-caution alert alert--warning"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 16 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u9700\u8981 ",Object(r.b)("inlineCode",{parentName:"p"},"Database")," \u591a\u79df\u6237\u65b9\u6848\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u9700\u8981\u91c7\u7528 ",Object(r.b)("inlineCode",{parentName:"p"},"AddDb")," \u6ce8\u518c\uff0c\u800c\u4e0d\u662f ",Object(r.b)("inlineCode",{parentName:"p"},"AddDbPool"),"\u3002\u539f\u56e0\u662f ",Object(r.b)("inlineCode",{parentName:"p"},"AddDbPool")," \u65b9\u5f0f\u6ce8\u518c\u540e\u7eed\u4e0d\u652f\u6301 ",Object(r.b)("inlineCode",{parentName:"p"},"OnConfiguring")," \u91cd\u5199\uff01\uff01\uff01"))),Object(r.b)("h3",{id:"1063-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e"},"10.6.3 \u6dfb\u52a0 ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u79cd\u5b50\u6570\u636e"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{8,12-30} title="Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"',"{8,12-30}":!0,title:'"Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Fur.EntityFramework.Core\n{\n public class TenantSeedData : IEntitySeedData\n {\n public IEnumerable HasData(DbContext dbContext, Type dbContextLocator)\n {\n return new List\n {\n new Tenant\n {\n TenantId=Guid.Parse("383AFB88-F519-FFF8-B364-6D563BF3687F"),\n Name="\u9ed8\u8ba4\u79df\u6237",\n Host="localhost:44313",\n CreatedTime=DateTime.Parse("2020-10-06 20:19:07"),\n ConnectionString="Data Source=./Fur.db" // \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32\n },\n new Tenant\n {\n TenantId=Guid.Parse("C5798CB6-16D6-0F42-EB56-59C695353BC0"),\n Name="\u5176\u4ed6\u79df\u6237",\n Host="localhost:5000",\n CreatedTime=DateTime.Parse("2020-10-06 20:20:32"),\n ConnectionString="Data Source=./Fur2.db" // \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32\n }\n };\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u8bf4\u660e")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u8be5\u6b65\u9aa4\u53ea\u5728 ",Object(r.b)("inlineCode",{parentName:"p"},"Code First")," \u65b9\u5f0f\u6267\u884c\uff0c",Object(r.b)("inlineCode",{parentName:"p"},"Database First")," \u65e0\u9700\u914d\u7f6e\u79cd\u5b50\u6570\u636e\u3002"))),Object(r.b)("h3",{id:"1064-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868"},"10.6.4 \u6839\u636e\u6a21\u578b\u521b\u5efa ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u8868"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Add-Migration add_tenant_table -Context MultiTenantDbContext\n")),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Update-Database -Context MultiTenantDbContext\n")),Object(r.b)("h3",{id:"1065-\u5b9e\u73b0-imultitenantondatabase-\u63a5\u53e3"},"10.6.5 \u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"h3"},"IMultiTenantOnDatabase")," \u63a5\u53e3"),Object(r.b)("p",null,"\u5728\u9700\u8981\u591a\u79df\u6237\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"p"},"IMultiTenantOnDatabase")," \u63a5\u53e3\uff0c\u5982\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{6,12-15}","{6,12-15}":!0}),"using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n public class FurDbContext : AppDbContext, IMultiTenantOnDatabase\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public string GetDatabaseConnectionString()\n {\n return base.Tenant.ConnectionString;\n }\n }\n}\n")),Object(r.b)("h3",{id:"1066-\u91cd\u5199-onconfiguring-\u65b9\u6cd5"},"10.6.6 \u91cd\u5199 ",Object(r.b)("inlineCode",{parentName:"h3"},"OnConfiguring")," \u65b9\u6cd5"),Object(r.b)("p",null,"\u5728\u9700\u8981\u591a\u79df\u6237\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u91cd\u5199 ",Object(r.b)("inlineCode",{parentName:"p"},"OnConfiguring")," \u65b9\u6cd5\u5e76\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{12-17}","{12-17}":!0}),"using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n public class FurDbContext : AppDbContext, IMultiTenantOnDatabase\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)\n {\n optionsBuilder.UseSqlite(GetDatabaseConnectionString());\n\n base.OnConfiguring(optionsBuilder);\n }\n\n public string GetDatabaseConnectionString()\n {\n return base.Tenant.ConnectionString;\n }\n }\n}\n")),Object(r.b)("img",{src:Object(o.a)("img/saas2.png")}),Object(r.b)("h2",{id:"107-\u57fa\u4e8e-schema-\u7684\u65b9\u5f0f"},"10.7 \u57fa\u4e8e ",Object(r.b)("inlineCode",{parentName:"h2"},"Schema")," \u7684\u65b9\u5f0f"),Object(r.b)("p",null,"\u6b64\u65b9\u5f0f\u5728\u4e2d\u5c0f\u578b\u4f01\u4e1a\u7cfb\u7edf\u4e2d\u4e5f\u4e0d\u5c11\u89c1\uff0c\u4e00\u4e2a\u79df\u6237\uff08\u5ba2\u6237\uff09\u5171\u4eab\u6570\u636e\u5e93\u4e14\u4e0d\u540c ",Object(r.b)("inlineCode",{parentName:"p"},"Schema"),"\u3002"),Object(r.b)("h3",{id:"1071-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.7.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{6-7} title="Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"',"{6-7}":!0,title:'"Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class MultiTenantDbContext : AppDbContext\n {\n public MultiTenantDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-important alert alert--info"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u591a\u79df\u6237\u64cd\u4f5c\u5efa\u8bae\u5355\u72ec\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u800c\u4e14\u9700\u6307\u5b9a ",Object(r.b)("inlineCode",{parentName:"p"},"MultiTenantDbContextLocator")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u3002"))),Object(r.b)("h3",{id:"1072-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.7.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{14}","{14}":!0}),"using Fur.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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 options.AddDbPool(DbProvider.Sqlite);\n });\n }\n }\n}\n")),Object(r.b)("h3",{id:"1073-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e"},"10.7.3 \u6dfb\u52a0 ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u79cd\u5b50\u6570\u636e"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{8,12-30} title="Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"',"{8,12-30}":!0,title:'"Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Fur.EntityFramework.Core\n{\n public class TenantSeedData : IEntitySeedData\n {\n public IEnumerable HasData(DbContext dbContext, Type dbContextLocator)\n {\n return new List\n {\n new Tenant\n {\n TenantId=Guid.Parse("383AFB88-F519-FFF8-B364-6D563BF3687F"),\n Name="\u9ed8\u8ba4\u79df\u6237",\n Host="localhost:44313",\n CreatedTime=DateTime.Parse("2020-10-06 20:19:07"),\n Schema="dbo" // Schema\n },\n new Tenant\n {\n TenantId=Guid.Parse("C5798CB6-16D6-0F42-EB56-59C695353BC0"),\n Name="\u5176\u4ed6\u79df\u6237",\n Host="localhost:5000",\n CreatedTime=DateTime.Parse("2020-10-06 20:20:32"),\n Schema="fur" // Schema\n }\n };\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u8bf4\u660e")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u8be5\u6b65\u9aa4\u53ea\u5728 ",Object(r.b)("inlineCode",{parentName:"p"},"Code First")," \u65b9\u5f0f\u6267\u884c\uff0c",Object(r.b)("inlineCode",{parentName:"p"},"Database First")," \u65e0\u9700\u914d\u7f6e\u79cd\u5b50\u6570\u636e\u3002"))),Object(r.b)("h3",{id:"1074-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868"},"10.7.4 \u6839\u636e\u6a21\u578b\u521b\u5efa ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u8868"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Add-Migration add_tenant_table -Context MultiTenantDbContext\n")),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Update-Database -Context MultiTenantDbContext\n")),Object(r.b)("h3",{id:"1075-\u5b9e\u73b0-imultitenantonschema-\u63a5\u53e3"},"10.7.5 \u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"h3"},"IMultiTenantOnSchema")," \u63a5\u53e3"),Object(r.b)("p",null,"\u5728\u9700\u8981\u591a\u79df\u6237\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"p"},"IMultiTenantOnSchema")," \u63a5\u53e3\uff0c\u5982\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{6,12-15}","{6,12-15}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class FurDbContext : AppDbContext, IMultiTenantOnSchema\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public string GetSchemaName()\n {\n return base.Tenant.Schema;\n }\n }\n}\n')),Object(r.b)("h3",{id:"1076-\u5173\u4e8e-code-first-\u6570\u636e\u8fc1\u79fb"},"10.7.6 \u5173\u4e8e ",Object(r.b)("inlineCode",{parentName:"h3"},"Code First \u6570\u636e\u8fc1\u79fb")),Object(r.b)("p",null,"\u57fa\u4e8e ",Object(r.b)("inlineCode",{parentName:"p"},"Schema")," \u65b9\u5f0f\u6bd4\u8f83\u7279\u522b\uff0c\u751f\u6210\u6570\u636e\u8fc1\u79fb\u7684\u65f6\u5019\u6ca1\u529e\u6cd5\u83b7\u53d6\u79df\u6237\u4fe1\u606f\uff0c\u6240\u4ee5\u5efa\u8bae",Object(r.b)("strong",{parentName:"p"},"\u5206\u5f00\u591a\u6b21\u8fc1\u79fb"),"\uff0c\u5982\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),'public string GetSchemaName()\n{\n return base.Tenant.Schema?? "\u79df\u6237\u4e00Schema";\n}\n')),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),'public string GetSchemaName()\n{\n return base.Tenant.Schema?? "\u79df\u6237\u4e8cSchema";\n}\n')),Object(r.b)("p",null,"\u8fd9\u6837\u5c31\u53ef\u4ee5\u5728\u8fc1\u79fb\u7684\u65f6\u5019\u751f\u6210\u591a\u6b21\u8fc1\u79fb\u4e86\u3002"),Object(r.b)("h2",{id:"108-\u53cd\u9988\u4e0e\u5efa\u8bae"},"10.8 \u53cd\u9988\u4e0e\u5efa\u8bae"),Object(r.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e0e\u6211\u4eec\u4ea4\u6d41")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u7ed9 Fur \u63d0 ",Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://gitee.com/monksoul/Fur/issues/new?issue"}),"Issue"),"\u3002"))))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/3e869f93.f969095c.js b/docs/3e869f93.fc3e563c.js similarity index 51% rename from docs/3e869f93.f969095c.js rename to docs/3e869f93.fc3e563c.js index 245b887d679..cebd4f6fc6b 100644 --- a/docs/3e869f93.f969095c.js +++ b/docs/3e869f93.fc3e563c.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[23],{138:function(e,t,n){"use strict";n.d(t,"a",(function(){return d})),n.d(t,"b",(function(){return O}));var a=n(0),i=n.n(a);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 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 b(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 p=i.a.createContext({}),l=function(e){var t=i.a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):b(b({},t),e)),n},d=function(e){var t=l(e.components);return i.a.createElement(p.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return i.a.createElement(i.a.Fragment,{},t)}},m=i.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,r=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),d=l(n),m=a,O=d["".concat(r,".").concat(m)]||d[m]||s[m]||o;return n?i.a.createElement(O,b(b({ref:t},p),{},{components:n})):i.a.createElement(O,b({ref:t},p))}));function O(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,r=new Array(o);r[0]=m;var b={};for(var c in t)hasOwnProperty.call(t,c)&&(b[c]=t[c]);b.originalType=e,b.mdxType="string"==typeof e?e:a,r[1]=b;for(var p=2;pAppDbContext",id:"912-appdbcontext",children:[]},{value:"9.1.3 AppDbContext \u548c DbContext \u533a\u522b",id:"913-appdbcontext-\u548c-dbcontext-\u533a\u522b",children:[]},{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",children:[{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",children:[]},{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",children:[]}]},{value:"9.1.5 \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32",id:"915-\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32",children:[{value:"9.1.5.1 Startup \u65b9\u5f0f\u914d\u7f6e",id:"9151-startup-\u65b9\u5f0f\u914d\u7f6e",children:[]},{value:"9.1.5.2 [AppDbContext] \u65b9\u5f0f\u914d\u7f6e",id:"9152-appdbcontext-\u65b9\u5f0f\u914d\u7f6e",children:[]},{value:"9.1.5.3 OnConfiguring \u65b9\u5f0f\u914d\u7f6e",id:"9153-onconfiguring-\u65b9\u5f0f\u914d\u7f6e",children:[]}]},{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",children:[]},{value:"9.1.7 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c",id:"917-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c",children:[]},{value:"9.1.8 \u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61",id:"918-\u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61",children:[]},{value:"9.1.9 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"919-\u53cd\u9988\u4e0e\u5efa\u8bae",children:[]}],p={rightToc:c};function l(e){var t=e.components,n=Object(i.a)(e,["components"]);return Object(o.b)("wrapper",Object(a.a)({},p,n,{components:t,mdxType:"MDXLayout"}),Object(o.b)("h2",{id:"911-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.1.1 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(o.b)("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"),Object(o.b)("p",null,"\u5728 ",Object(o.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u4e2d\uff0c\u9ed8\u8ba4\u96c6\u6210\u4e86\u5fae\u8f6f\u4eb2\u513f\u5b50\uff1a",Object(o.b)("inlineCode",{parentName:"p"},"EntityFramework Core")," \uff0c\u4e5f\u5c31\u662f\u901a\u5e38\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6307\u7684\u662f ",Object(o.b)("inlineCode",{parentName:"p"},"DbContext")," \u7c7b\u6216\u5b83\u7684\u5b9e\u73b0\u7c7b\u3002"),Object(o.b)("h2",{id:"912-appdbcontext"},"9.1.2 ",Object(o.b)("inlineCode",{parentName:"h2"},"AppDbContext")),Object(o.b)("p",null,"\u5728\u6211\u4eec\u5b9e\u9645\u9879\u76ee\u5f00\u53d1\u8fc7\u7a0b\u4e2d\uff0c\u4f7f\u7528 ",Object(o.b)("inlineCode",{parentName:"p"},"EFCore")," \u63d0\u4f9b\u7684 ",Object(o.b)("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"),Object(o.b)("p",null,"\u6240\u4ee5\uff0c",Object(o.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",Object(o.b)("inlineCode",{parentName:"p"},"AppDbContext")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u8be5\u4e0a\u4e0b\u6587\u7ee7\u627f\u81ea ",Object(o.b)("inlineCode",{parentName:"p"},"DbContext"),"\u3002"),Object(o.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(o.b)("h5",{parentName:"div"},Object(o.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(o.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(o.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u8bf4\u660e")),Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(o.b)("p",{parentName:"div"},"\u540e\u7eed\u7ae0\u8282\uff0c\u7686\u91c7\u7528 ",Object(o.b)("inlineCode",{parentName:"p"},"EFCore")," \u4ee3\u66ff ",Object(o.b)("inlineCode",{parentName:"p"},"EntityFramework Core"),"\u3002"))),Object(o.b)("h2",{id:"913-appdbcontext-\u548c-dbcontext-\u533a\u522b"},"9.1.3 ",Object(o.b)("inlineCode",{parentName:"h2"},"AppDbContext")," \u548c ",Object(o.b)("inlineCode",{parentName:"h2"},"DbContext")," \u533a\u522b"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u7ee7\u627f\u81ea ",Object(o.b)("inlineCode",{parentName:"li"},"DbContext"),"\uff0c\u5177\u5907 ",Object(o.b)("inlineCode",{parentName:"li"},"DbContext")," \u6240\u6709\u529f\u80fd\u3002"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u591a\u6570\u636e\u5e93\u64cd\u4f5c\u6cdb\u578b\u7248\u672c\uff0c\u5982\uff1a",Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u81ea\u52a8\u914d\u7f6e\u5b9e\u4f53\u4fe1\u606f\uff0c\u65e0\u9700\u5728 ",Object(o.b)("inlineCode",{parentName:"li"},"OnModelCreating")," \u4e2d\u914d\u7f6e"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u5185\u7f6e\u591a\u79df\u6237\u652f\u6301"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u5168\u5c40\u6a21\u578b\u914d\u7f6e\u62e6\u622a\u5668"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u6570\u636e\u63d0\u4ea4\u66f4\u6539\u591a\u4e2a\u4e8b\u4ef6"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u63d0\u4f9b\u66f4\u52a0\u5f3a\u5927\u7684\u6a21\u578b\u64cd\u4f5c\u80fd\u529b\uff0c\u5982\u679c ",Object(o.b)("inlineCode",{parentName:"li"},"Sql")," \u64cd\u4f5c\uff0c\u8bfb\u5199\u5206\u79bb\u7b49"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u80fd\u591f\u5f97\u5230 ",Object(o.b)("inlineCode",{parentName:"li"},"Fur")," \u6846\u67b6\u66f4\u591a\u7684\u529f\u80fd\u652f\u6301")),Object(o.b)("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"),Object(o.b)("p",null,"\u5728 ",Object(o.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u4e2d\u4e86\uff0c\u63d0\u4f9b\u4e86\u4e24\u79cd ",Object(o.b)("inlineCode",{parentName:"p"},"AppDbContext")," \u5b9a\u4e49\u65b9\u5f0f\uff1a"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u64cd\u4f5c\u9ed8\u8ba4\u6570\u636e\u5e93"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u64cd\u4f5c N \u4e2a\u6570\u636e\u5e93")),Object(o.b)("p",null,"\u5176\u4e2d ",Object(o.b)("inlineCode",{parentName:"p"},"AppDbContext")," \u9ed8\u8ba4\u7ee7\u627f\u81ea ",Object(o.b)("inlineCode",{parentName:"p"},"AppDbContext"),"\u3002"),Object(o.b)("p",null,"\u4e0b\u9762\u662f\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u521b\u5efa\u7684\u591a\u4e2a\u4f8b\u5b50\uff1a"),Object(o.b)("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"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{1,6,12}","{1,6,12}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("\u8fde\u63a5\u5b57\u7b26\u4e32\u6216appsetting.json \u952e")]\n public class FurDbContext : AppDbContext // \u7ee7\u627f AppDbContext<> \u7c7b\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(o.b)("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"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{1,6,12}","{1,6,12}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.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')),Object(o.b)("div",{className:"admonition admonition-important alert alert--info"},Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(o.b)("h5",{parentName:"div"},Object(o.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(o.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(o.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(o.b)("p",{parentName:"div"},"\u6240\u6709\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u90fd\u5e94\u8be5\u5728 ",Object(o.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u9879\u76ee\u4e2d\u521b\u5efa\u3002\u5173\u4e8e ",Object(o.b)("inlineCode",{parentName:"p"},"TDbContextLocator")," \u5c06\u5728\u4e0b\u4e00\u7ae0\u8282 \u300a",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"dbcontext-locator"}),"9.2 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668"),"\u300b\u9610\u8ff0\u3002"))),Object(o.b)("h2",{id:"915-\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32"},"9.1.5 \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32"),Object(o.b)("p",null,Object(o.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u63d0\u4f9b\u591a\u79cd\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u65b9\u5f0f\uff1a"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"\u5728 ",Object(o.b)("inlineCode",{parentName:"li"},"Startup")," \u4e2d\u6dfb\u52a0\u670d\u52a1\uff1a",Object(o.b)("inlineCode",{parentName:"li"},'AddSqlServerPool("\u8fde\u63a5\u5b57\u7b26\u4e32")')," \u65b9\u5f0f"),Object(o.b)("li",{parentName:"ul"},"\u4f7f\u7528 ",Object(o.b)("inlineCode",{parentName:"li"},'[AppDbContext("\u8fde\u63a5\u5b57\u7b26\u4e32/Key")]')," \u7279\u6027\u65b9\u5f0f\uff08\u53ea\u5728 ",Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext \u5b9e\u73b0\u7c7b\u6709\u6548"),"\uff09",Object(o.b)("strong",{parentName:"li"},"\u63a8\u8350")),Object(o.b)("li",{parentName:"ul"},"\u901a\u8fc7\u91cd\u5199 ",Object(o.b)("inlineCode",{parentName:"li"},"OnConfiguring(DbContextOptionsBuilder optionsBuilder)")," \u914d\u7f6e")),Object(o.b)("h3",{id:"9151-startup-\u65b9\u5f0f\u914d\u7f6e"},"9.1.5.1 ",Object(o.b)("inlineCode",{parentName:"h3"},"Startup")," \u65b9\u5f0f\u914d\u7f6e"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{12-19} title="Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"',"{12-19}":!0,title:'"Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"'}),'using Fur.DependencyInjection;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.EntityFramework.Core\n{\n [Startup(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, "\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, "\u8fde\u63a5\u5b57\u7b26\u4e32");\n });\n }\n }\n}\n')),Object(o.b)("h3",{id:"9152-appdbcontext-\u65b9\u5f0f\u914d\u7f6e"},"9.1.5.2 ",Object(o.b)("inlineCode",{parentName:"h3"},"[AppDbContext]")," \u65b9\u5f0f\u914d\u7f6e"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{1,6}","{1,6}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("DbConnectionString")] // \u652f\u6301 `appsetting.json` \u540d\u6216 \u8fde\u63a5\u5b57\u7b26\u4e32\n public class FurDbContext : AppDbContext\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(o.b)("div",{className:"admonition admonition-tip alert alert--success"},Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(o.b)("h5",{parentName:"div"},Object(o.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(o.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"12",height:"16",viewBox:"0 0 12 16"}),Object(o.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u5c0f\u63d0\u793a")),Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(o.b)("p",{parentName:"div"},Object(o.b)("inlineCode",{parentName:"p"},"Fur")," \u63a8\u8350\u4f7f\u7528\u6b64\u65b9\u5f0f\u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u3002"))),Object(o.b)("p",null,Object(o.b)("strong",{parentName:"p"},Object(o.b)("inlineCode",{parentName:"strong"},"[AppDbContext]"))," \u5185\u7f6e\u5c5e\u6027\uff1a"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"ConnectionString"),"\uff1a\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u6216\u914d\u7f6e\u6587\u4ef6\u4e2d\u7684\u8def\u5f84\uff08\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e\u67e5\u627e\uff09\uff0c\u6216 ",Object(o.b)("inlineCode",{parentName:"li"},"appsetting.json")," \u7684 ",Object(o.b)("inlineCode",{parentName:"li"},"ConnectionStrings")," \u914d\u7f6e\u5b57\u7b26\u4e32"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"TablePrefix"),"\uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u8868\u7edf\u4e00\u524d\u7f00"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"TableSuffix"),"\uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u8868\u7edf\u4e00\u540e\u7f00")),Object(o.b)("h3",{id:"9153-onconfiguring-\u65b9\u5f0f\u914d\u7f6e"},"9.1.5.3 ",Object(o.b)("inlineCode",{parentName:"h3"},"OnConfiguring")," \u65b9\u5f0f\u914d\u7f6e"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{16-20}","{16-20}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n public class FurDbContext : AppDbContext\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurDbContext(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')),Object(o.b)("div",{className:"admonition admonition-important alert alert--info"},Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(o.b)("h5",{parentName:"div"},Object(o.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(o.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(o.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(o.b)("p",{parentName:"div"},"\u8fd9\u4e09\u79cd\u65b9\u5f0f\u53ef\u4ee5\u540c\u65f6\u4f7f\u7528\uff0c\u4f46\u662f\u6709\u4f18\u5148\u7ea7\uff1a",Object(o.b)("inlineCode",{parentName:"p"},"[AppDbContext]")," -> ",Object(o.b)("inlineCode",{parentName:"p"},"Startup")," -> ",Object(o.b)("inlineCode",{parentName:"p"},"OnConfiguring"),"\uff08\u4f4e\u5230\u9ad8\uff09"),Object(o.b)("p",{parentName:"div"},"\u4e5f\u5c31\u662f ",Object(o.b)("inlineCode",{parentName:"p"},"OnConfiguring")," \u914d\u7f6e\u4f1a\u8986\u76d6 ",Object(o.b)("inlineCode",{parentName:"p"},"Startup")," \u914d\u7f6e\uff0c",Object(o.b)("inlineCode",{parentName:"p"},"Startup")," \u914d\u7f6e\u4f1a\u8986\u76d6 ",Object(o.b)("inlineCode",{parentName:"p"},"[AppDbContext]")," \u914d\u7f6e\u6240\u914d\u7f6e\u7684\u8fde\u63a5\u5b57\u7b26\u4e32\u3002"))),Object(o.b)("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"),Object(o.b)("div",{className:"admonition admonition-important alert alert--info"},Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(o.b)("h5",{parentName:"div"},Object(o.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(o.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(o.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(o.b)("p",{parentName:"div"},"\u5728 ",Object(o.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u4e2d\uff0c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u9700\u5b9a\u4e49\u5728 ",Object(o.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u4e2d\uff0c\u4e14\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u90fd\u5fc5\u987b\u62e5\u6709\u552f\u4e00\u7684 ",Object(o.b)("inlineCode",{parentName:"p"},"DbContextLocator")," \u5b9a\u4f4d\u5668"))),Object(o.b)("h2",{id:"917-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c"},"9.1.7 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c"),Object(o.b)("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\u6539\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u5e76\u6307\u5b9a\u6570\u636e\u5e93\u7c7b\u578b\uff0c\u5982\uff1a"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{11-13} title="Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"',"{11-13}":!0,title:'"Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"'}),"using Fur.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.EntityFramework.Core\n{\n [Startup(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")),Object(o.b)("p",null,"\u5982\u679c\u6709\u591a\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\uff0c",Object(o.b)("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"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"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")),Object(o.b)("h2",{id:"918-\u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61"},"9.1.8 \u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61"),Object(o.b)("p",null,"\u5728 ",Object(o.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u4e2d\uff0c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u662f\u5b9a\u4e49\u5728 ",Object(o.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u9879\u76ee\u5c42\uff0c\u5e76\u4e14\u8be5\u5c42\u4e0d\u88ab ",Object(o.b)("inlineCode",{parentName:"p"},"Fur.Application")," \u548c ",Object(o.b)("inlineCode",{parentName:"p"},"Fur.Core")," \u7b49\u5c42\u5f15\u7528\u3002"),Object(o.b)("p",null,"\u6240\u4ee5\u5c31\u4e0d\u80fd\u76f4\u63a5\u5728 ",Object(o.b)("inlineCode",{parentName:"p"},"Fur.Application")," \u9879\u76ee\u5c42\u76f4\u63a5\u4f7f\u7528 ",Object(o.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u5b9a\u4e49\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u3002"),Object(o.b)("p",null,Object(o.b)("inlineCode",{parentName:"p"},"Fur")," \u4e3a\u4e86\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\uff0c\u63d0\u4f9b\u4e86\u4e24\u79cd\u65b9\u5f0f\u5904\u7406\uff1a"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"respository.DbContext")," \uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61\uff0c\u8fd4\u56de\u662f ",Object(o.b)("inlineCode",{parentName:"li"},"DbContext")," \u62bd\u8c61\u7c7b\u578b"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"respository.DynamicDbContext"),"\uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61\uff0c\u8fd4\u56de\u7684\u662f ",Object(o.b)("inlineCode",{parentName:"li"},"dynamic")," \u7c7b\u578b")),Object(o.b)("p",null,"\u5982\u679c\u4f60\u53ea\u662f\u60f3\u4f7f\u7528 ",Object(o.b)("inlineCode",{parentName:"p"},"DbContext")," \u7684\u529f\u80fd\uff0c\u76f4\u63a5\u4f7f\u7528 ",Object(o.b)("inlineCode",{parentName:"p"},"respository.DbContext")," \u5373\u53ef\uff0c\u5982\uff1a"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"respository.DbContext.SaveChanges();\n")),Object(o.b)("p",null,"\u5982\u679c\u4f60\u60f3\u80fd\u591f\u83b7\u53d6\u5177\u4f53\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u7c7b\u578b\uff0c\u5982 ",Object(o.b)("inlineCode",{parentName:"p"},"MyDbContext"),"\uff0c\u90a3\u4e48\u4f7f\u7528 ",Object(o.b)("inlineCode",{parentName:"p"},"respository.DynamicDbContext")," \u5c31\u53ef\u4ee5\u83b7\u53d6\u5230\u5177\u4f53\u7684 ",Object(o.b)("inlineCode",{parentName:"p"},"MyDbContext")," \u7c7b\u578b\u3002\u5982\uff1a"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"var persons = respository.DynamicDbContext.Persons.Find(1);\nvar users = respository.DynamicDbContext.Users;\n")),Object(o.b)("p",null,"\u8fd9\u6837\u5c31\u53ef\u4ee5\u76f4\u63a5\u64cd\u4f5c ",Object(o.b)("inlineCode",{parentName:"p"},"MyDbContext")," \u5b9a\u4e49\u7684\u5c5e\u6027\u548c\u65b9\u6cd5\u4e86\u3002"),Object(o.b)("h2",{id:"919-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.1.9 \u53cd\u9988\u4e0e\u5efa\u8bae"),Object(o.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(o.b)("h5",{parentName:"div"},Object(o.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(o.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(o.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e0e\u6211\u4eec\u4ea4\u6d41")),Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(o.b)("p",{parentName:"div"},"\u7ed9 Fur \u63d0 ",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"https://gitee.com/monksoul/Fur/issues/new?issue"}),"Issue"),"\u3002"))),Object(o.b)("hr",null),Object(o.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(o.b)("h5",{parentName:"div"},Object(o.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(o.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(o.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e86\u89e3\u66f4\u591a")),Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(o.b)("p",{parentName:"div"},"\u60f3\u4e86\u89e3\u66f4\u591a ",Object(o.b)("inlineCode",{parentName:"p"},"\u6570\u636e\u5e93\u4e0a\u4e0b\u6587")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"https://docs.microsoft.com/zh-cn/ef/core/miscellaneous/configuring-dbcontext"}),"EF Core - \u914d\u7f6e DbContext")," \u7ae0\u8282\u3002"))))}l.isMDXComponent=!0}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[23],{138:function(e,t,n){"use strict";n.d(t,"a",(function(){return d})),n.d(t,"b",(function(){return O}));var a=n(0),i=n.n(a);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 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 b(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 p=i.a.createContext({}),l=function(e){var t=i.a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):b(b({},t),e)),n},d=function(e){var t=l(e.components);return i.a.createElement(p.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return i.a.createElement(i.a.Fragment,{},t)}},m=i.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,r=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),d=l(n),m=a,O=d["".concat(r,".").concat(m)]||d[m]||s[m]||o;return n?i.a.createElement(O,b(b({ref:t},p),{},{components:n})):i.a.createElement(O,b({ref:t},p))}));function O(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,r=new Array(o);r[0]=m;var b={};for(var c in t)hasOwnProperty.call(t,c)&&(b[c]=t[c]);b.originalType=e,b.mdxType="string"==typeof e?e:a,r[1]=b;for(var p=2;pAppDbContext",id:"912-appdbcontext",children:[]},{value:"9.1.3 AppDbContext \u548c DbContext \u533a\u522b",id:"913-appdbcontext-\u548c-dbcontext-\u533a\u522b",children:[]},{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",children:[{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",children:[]},{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",children:[]}]},{value:"9.1.5 \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32",id:"915-\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32",children:[{value:"9.1.5.1 Startup \u65b9\u5f0f\u914d\u7f6e",id:"9151-startup-\u65b9\u5f0f\u914d\u7f6e",children:[]},{value:"9.1.5.2 [AppDbContext] \u65b9\u5f0f\u914d\u7f6e",id:"9152-appdbcontext-\u65b9\u5f0f\u914d\u7f6e",children:[]},{value:"9.1.5.3 OnConfiguring \u65b9\u5f0f\u914d\u7f6e",id:"9153-onconfiguring-\u65b9\u5f0f\u914d\u7f6e",children:[]}]},{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",children:[]},{value:"9.1.7 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c",id:"917-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c",children:[]},{value:"9.1.8 \u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61",id:"918-\u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61",children:[]},{value:"9.1.9 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"919-\u53cd\u9988\u4e0e\u5efa\u8bae",children:[]}],p={rightToc:c};function l(e){var t=e.components,n=Object(i.a)(e,["components"]);return Object(o.b)("wrapper",Object(a.a)({},p,n,{components:t,mdxType:"MDXLayout"}),Object(o.b)("h2",{id:"911-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.1.1 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(o.b)("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"),Object(o.b)("p",null,"\u5728 ",Object(o.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u4e2d\uff0c\u9ed8\u8ba4\u96c6\u6210\u4e86\u5fae\u8f6f\u4eb2\u513f\u5b50\uff1a",Object(o.b)("inlineCode",{parentName:"p"},"EntityFramework Core")," \uff0c\u4e5f\u5c31\u662f\u901a\u5e38\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6307\u7684\u662f ",Object(o.b)("inlineCode",{parentName:"p"},"DbContext")," \u7c7b\u6216\u5b83\u7684\u5b9e\u73b0\u7c7b\u3002"),Object(o.b)("h2",{id:"912-appdbcontext"},"9.1.2 ",Object(o.b)("inlineCode",{parentName:"h2"},"AppDbContext")),Object(o.b)("p",null,"\u5728\u6211\u4eec\u5b9e\u9645\u9879\u76ee\u5f00\u53d1\u8fc7\u7a0b\u4e2d\uff0c\u4f7f\u7528 ",Object(o.b)("inlineCode",{parentName:"p"},"EFCore")," \u63d0\u4f9b\u7684 ",Object(o.b)("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"),Object(o.b)("p",null,"\u6240\u4ee5\uff0c",Object(o.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",Object(o.b)("inlineCode",{parentName:"p"},"AppDbContext")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u8be5\u4e0a\u4e0b\u6587\u7ee7\u627f\u81ea ",Object(o.b)("inlineCode",{parentName:"p"},"DbContext"),"\u3002"),Object(o.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(o.b)("h5",{parentName:"div"},Object(o.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(o.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(o.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u8bf4\u660e")),Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(o.b)("p",{parentName:"div"},"\u540e\u7eed\u7ae0\u8282\uff0c\u7686\u91c7\u7528 ",Object(o.b)("inlineCode",{parentName:"p"},"EFCore")," \u4ee3\u66ff ",Object(o.b)("inlineCode",{parentName:"p"},"EntityFramework Core"),"\u3002"))),Object(o.b)("h2",{id:"913-appdbcontext-\u548c-dbcontext-\u533a\u522b"},"9.1.3 ",Object(o.b)("inlineCode",{parentName:"h2"},"AppDbContext")," \u548c ",Object(o.b)("inlineCode",{parentName:"h2"},"DbContext")," \u533a\u522b"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u7ee7\u627f\u81ea ",Object(o.b)("inlineCode",{parentName:"li"},"DbContext"),"\uff0c\u5177\u5907 ",Object(o.b)("inlineCode",{parentName:"li"},"DbContext")," \u6240\u6709\u529f\u80fd\u3002"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u591a\u6570\u636e\u5e93\u64cd\u4f5c\u6cdb\u578b\u7248\u672c\uff0c\u5982\uff1a",Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u81ea\u52a8\u914d\u7f6e\u5b9e\u4f53\u4fe1\u606f\uff0c\u65e0\u9700\u5728 ",Object(o.b)("inlineCode",{parentName:"li"},"OnModelCreating")," \u4e2d\u914d\u7f6e"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u5185\u7f6e\u591a\u79df\u6237\u652f\u6301"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u5168\u5c40\u6a21\u578b\u914d\u7f6e\u62e6\u622a\u5668"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u6570\u636e\u63d0\u4ea4\u66f4\u6539\u591a\u4e2a\u4e8b\u4ef6"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u63d0\u4f9b\u66f4\u52a0\u5f3a\u5927\u7684\u6a21\u578b\u64cd\u4f5c\u80fd\u529b\uff0c\u5982\u679c ",Object(o.b)("inlineCode",{parentName:"li"},"Sql")," \u64cd\u4f5c\uff0c\u8bfb\u5199\u5206\u79bb\u7b49"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u80fd\u591f\u5f97\u5230 ",Object(o.b)("inlineCode",{parentName:"li"},"Fur")," \u6846\u67b6\u66f4\u591a\u7684\u529f\u80fd\u652f\u6301")),Object(o.b)("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"),Object(o.b)("p",null,"\u5728 ",Object(o.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u4e2d\u4e86\uff0c\u63d0\u4f9b\u4e86\u4e24\u79cd ",Object(o.b)("inlineCode",{parentName:"p"},"AppDbContext")," \u5b9a\u4e49\u65b9\u5f0f\uff1a"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u64cd\u4f5c\u9ed8\u8ba4\u6570\u636e\u5e93"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u64cd\u4f5c N \u4e2a\u6570\u636e\u5e93")),Object(o.b)("p",null,"\u5176\u4e2d ",Object(o.b)("inlineCode",{parentName:"p"},"AppDbContext")," \u9ed8\u8ba4\u7ee7\u627f\u81ea ",Object(o.b)("inlineCode",{parentName:"p"},"AppDbContext"),"\u3002"),Object(o.b)("p",null,"\u4e0b\u9762\u662f\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u521b\u5efa\u7684\u591a\u4e2a\u4f8b\u5b50\uff1a"),Object(o.b)("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"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{1,6,12}","{1,6,12}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("\u8fde\u63a5\u5b57\u7b26\u4e32\u6216appsetting.json \u952e")]\n public class FurDbContext : AppDbContext // \u7ee7\u627f AppDbContext<> \u7c7b\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(o.b)("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"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{1,6,12}","{1,6,12}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.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')),Object(o.b)("div",{className:"admonition admonition-important alert alert--info"},Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(o.b)("h5",{parentName:"div"},Object(o.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(o.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(o.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(o.b)("p",{parentName:"div"},"\u6240\u6709\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u90fd\u5e94\u8be5\u5728 ",Object(o.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u9879\u76ee\u4e2d\u521b\u5efa\u3002\u5173\u4e8e ",Object(o.b)("inlineCode",{parentName:"p"},"TDbContextLocator")," \u5c06\u5728\u4e0b\u4e00\u7ae0\u8282 \u300a",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"dbcontext-locator"}),"9.2 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668"),"\u300b\u9610\u8ff0\u3002"))),Object(o.b)("h2",{id:"915-\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32"},"9.1.5 \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32"),Object(o.b)("p",null,Object(o.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u63d0\u4f9b\u591a\u79cd\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u65b9\u5f0f\uff1a"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"\u5728 ",Object(o.b)("inlineCode",{parentName:"li"},"Startup")," \u4e2d\u6dfb\u52a0\u670d\u52a1\uff1a",Object(o.b)("inlineCode",{parentName:"li"},'AddSqlServerPool("\u8fde\u63a5\u5b57\u7b26\u4e32")')," \u65b9\u5f0f"),Object(o.b)("li",{parentName:"ul"},"\u4f7f\u7528 ",Object(o.b)("inlineCode",{parentName:"li"},'[AppDbContext("\u8fde\u63a5\u5b57\u7b26\u4e32/Key")]')," \u7279\u6027\u65b9\u5f0f\uff08\u53ea\u5728 ",Object(o.b)("inlineCode",{parentName:"li"},"AppDbContext \u5b9e\u73b0\u7c7b\u6709\u6548"),"\uff09",Object(o.b)("strong",{parentName:"li"},"\u63a8\u8350")),Object(o.b)("li",{parentName:"ul"},"\u901a\u8fc7\u91cd\u5199 ",Object(o.b)("inlineCode",{parentName:"li"},"OnConfiguring(DbContextOptionsBuilder optionsBuilder)")," \u914d\u7f6e")),Object(o.b)("h3",{id:"9151-startup-\u65b9\u5f0f\u914d\u7f6e"},"9.1.5.1 ",Object(o.b)("inlineCode",{parentName:"h3"},"Startup")," \u65b9\u5f0f\u914d\u7f6e"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{12-19} title="Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"',"{12-19}":!0,title:'"Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"'}),'using Fur.DependencyInjection;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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, "\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, "\u8fde\u63a5\u5b57\u7b26\u4e32");\n });\n }\n }\n}\n')),Object(o.b)("h3",{id:"9152-appdbcontext-\u65b9\u5f0f\u914d\u7f6e"},"9.1.5.2 ",Object(o.b)("inlineCode",{parentName:"h3"},"[AppDbContext]")," \u65b9\u5f0f\u914d\u7f6e"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{1,6}","{1,6}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("DbConnectionString")] // \u652f\u6301 `appsetting.json` \u540d\u6216 \u8fde\u63a5\u5b57\u7b26\u4e32\n public class FurDbContext : AppDbContext\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(o.b)("div",{className:"admonition admonition-tip alert alert--success"},Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(o.b)("h5",{parentName:"div"},Object(o.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(o.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"12",height:"16",viewBox:"0 0 12 16"}),Object(o.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u5c0f\u63d0\u793a")),Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(o.b)("p",{parentName:"div"},Object(o.b)("inlineCode",{parentName:"p"},"Fur")," \u63a8\u8350\u4f7f\u7528\u6b64\u65b9\u5f0f\u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u3002"))),Object(o.b)("p",null,Object(o.b)("strong",{parentName:"p"},Object(o.b)("inlineCode",{parentName:"strong"},"[AppDbContext]"))," \u5185\u7f6e\u5c5e\u6027\uff1a"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"ConnectionString"),"\uff1a\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u6216\u914d\u7f6e\u6587\u4ef6\u4e2d\u7684\u8def\u5f84\uff08\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e\u67e5\u627e\uff09\uff0c\u6216 ",Object(o.b)("inlineCode",{parentName:"li"},"appsetting.json")," \u7684 ",Object(o.b)("inlineCode",{parentName:"li"},"ConnectionStrings")," \u914d\u7f6e\u5b57\u7b26\u4e32"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"TablePrefix"),"\uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u8868\u7edf\u4e00\u524d\u7f00"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"TableSuffix"),"\uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u8868\u7edf\u4e00\u540e\u7f00")),Object(o.b)("h3",{id:"9153-onconfiguring-\u65b9\u5f0f\u914d\u7f6e"},"9.1.5.3 ",Object(o.b)("inlineCode",{parentName:"h3"},"OnConfiguring")," \u65b9\u5f0f\u914d\u7f6e"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{16-20}","{16-20}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n public class FurDbContext : AppDbContext\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurDbContext(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')),Object(o.b)("div",{className:"admonition admonition-important alert alert--info"},Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(o.b)("h5",{parentName:"div"},Object(o.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(o.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(o.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(o.b)("p",{parentName:"div"},"\u8fd9\u4e09\u79cd\u65b9\u5f0f\u53ef\u4ee5\u540c\u65f6\u4f7f\u7528\uff0c\u4f46\u662f\u6709\u4f18\u5148\u7ea7\uff1a",Object(o.b)("inlineCode",{parentName:"p"},"[AppDbContext]")," -> ",Object(o.b)("inlineCode",{parentName:"p"},"Startup")," -> ",Object(o.b)("inlineCode",{parentName:"p"},"OnConfiguring"),"\uff08\u4f4e\u5230\u9ad8\uff09"),Object(o.b)("p",{parentName:"div"},"\u4e5f\u5c31\u662f ",Object(o.b)("inlineCode",{parentName:"p"},"OnConfiguring")," \u914d\u7f6e\u4f1a\u8986\u76d6 ",Object(o.b)("inlineCode",{parentName:"p"},"Startup")," \u914d\u7f6e\uff0c",Object(o.b)("inlineCode",{parentName:"p"},"Startup")," \u914d\u7f6e\u4f1a\u8986\u76d6 ",Object(o.b)("inlineCode",{parentName:"p"},"[AppDbContext]")," \u914d\u7f6e\u6240\u914d\u7f6e\u7684\u8fde\u63a5\u5b57\u7b26\u4e32\u3002"))),Object(o.b)("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"),Object(o.b)("div",{className:"admonition admonition-important alert alert--info"},Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(o.b)("h5",{parentName:"div"},Object(o.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(o.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(o.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(o.b)("p",{parentName:"div"},"\u5728 ",Object(o.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u4e2d\uff0c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u9700\u5b9a\u4e49\u5728 ",Object(o.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u4e2d\uff0c\u4e14\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u90fd\u5fc5\u987b\u62e5\u6709\u552f\u4e00\u7684 ",Object(o.b)("inlineCode",{parentName:"p"},"DbContextLocator")," \u5b9a\u4f4d\u5668"))),Object(o.b)("h2",{id:"917-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c"},"9.1.7 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c"),Object(o.b)("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"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{11-13} title="Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"',"{11-13}":!0,title:'"Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"'}),"using Fur.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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")),Object(o.b)("p",null,"\u5982\u679c\u6709\u591a\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\uff0c",Object(o.b)("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"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"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")),Object(o.b)("h2",{id:"918-\u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61"},"9.1.8 \u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61"),Object(o.b)("p",null,"\u5728 ",Object(o.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u4e2d\uff0c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u662f\u5b9a\u4e49\u5728 ",Object(o.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u9879\u76ee\u5c42\uff0c\u5e76\u4e14\u8be5\u5c42\u4e0d\u88ab ",Object(o.b)("inlineCode",{parentName:"p"},"Fur.Application")," \u548c ",Object(o.b)("inlineCode",{parentName:"p"},"Fur.Core")," \u7b49\u5c42\u5f15\u7528\u3002"),Object(o.b)("p",null,"\u6240\u4ee5\u5c31\u4e0d\u80fd\u76f4\u63a5\u5728 ",Object(o.b)("inlineCode",{parentName:"p"},"Fur.Application")," \u9879\u76ee\u5c42\u76f4\u63a5\u4f7f\u7528 ",Object(o.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u5b9a\u4e49\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u3002"),Object(o.b)("p",null,Object(o.b)("inlineCode",{parentName:"p"},"Fur")," \u4e3a\u4e86\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\uff0c\u63d0\u4f9b\u4e86\u4e24\u79cd\u65b9\u5f0f\u5904\u7406\uff1a"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"respository.DbContext")," \uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61\uff0c\u8fd4\u56de\u662f ",Object(o.b)("inlineCode",{parentName:"li"},"DbContext")," \u62bd\u8c61\u7c7b\u578b"),Object(o.b)("li",{parentName:"ul"},Object(o.b)("inlineCode",{parentName:"li"},"respository.DynamicDbContext"),"\uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61\uff0c\u8fd4\u56de\u7684\u662f ",Object(o.b)("inlineCode",{parentName:"li"},"dynamic")," \u7c7b\u578b")),Object(o.b)("p",null,"\u5982\u679c\u4f60\u53ea\u662f\u60f3\u4f7f\u7528 ",Object(o.b)("inlineCode",{parentName:"p"},"DbContext")," \u7684\u529f\u80fd\uff0c\u76f4\u63a5\u4f7f\u7528 ",Object(o.b)("inlineCode",{parentName:"p"},"respository.DbContext")," \u5373\u53ef\uff0c\u5982\uff1a"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"respository.DbContext.SaveChanges();\n")),Object(o.b)("p",null,"\u5982\u679c\u4f60\u60f3\u80fd\u591f\u83b7\u53d6\u5177\u4f53\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u7c7b\u578b\uff0c\u5982 ",Object(o.b)("inlineCode",{parentName:"p"},"MyDbContext"),"\uff0c\u90a3\u4e48\u4f7f\u7528 ",Object(o.b)("inlineCode",{parentName:"p"},"respository.DynamicDbContext")," \u5c31\u53ef\u4ee5\u83b7\u53d6\u5230\u5177\u4f53\u7684 ",Object(o.b)("inlineCode",{parentName:"p"},"MyDbContext")," \u7c7b\u578b\u3002\u5982\uff1a"),Object(o.b)("pre",null,Object(o.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"var persons = respository.DynamicDbContext.Persons.Find(1);\nvar users = respository.DynamicDbContext.Users;\n")),Object(o.b)("p",null,"\u8fd9\u6837\u5c31\u53ef\u4ee5\u76f4\u63a5\u64cd\u4f5c ",Object(o.b)("inlineCode",{parentName:"p"},"MyDbContext")," \u5b9a\u4e49\u7684\u5c5e\u6027\u548c\u65b9\u6cd5\u4e86\u3002"),Object(o.b)("h2",{id:"919-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.1.9 \u53cd\u9988\u4e0e\u5efa\u8bae"),Object(o.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(o.b)("h5",{parentName:"div"},Object(o.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(o.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(o.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e0e\u6211\u4eec\u4ea4\u6d41")),Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(o.b)("p",{parentName:"div"},"\u7ed9 Fur \u63d0 ",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"https://gitee.com/monksoul/Fur/issues/new?issue"}),"Issue"),"\u3002"))),Object(o.b)("hr",null),Object(o.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(o.b)("h5",{parentName:"div"},Object(o.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(o.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(o.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e86\u89e3\u66f4\u591a")),Object(o.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(o.b)("p",{parentName:"div"},"\u60f3\u4e86\u89e3\u66f4\u591a ",Object(o.b)("inlineCode",{parentName:"p"},"\u6570\u636e\u5e93\u4e0a\u4e0b\u6587")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",Object(o.b)("a",Object(a.a)({parentName:"p"},{href:"https://docs.microsoft.com/zh-cn/ef/core/miscellaneous/configuring-dbcontext"}),"EF Core - \u914d\u7f6e DbContext")," \u7ae0\u8282\u3002"))))}l.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/404.html b/docs/404.html index 191ac6e1c12..79d1d4da9fa 100644 --- a/docs/404.html +++ b/docs/404.html @@ -6,14 +6,14 @@ Page Not Found | Fur - +

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/docs/4dbcf072.ac2f7683.js b/docs/4dbcf072.42badb24.js similarity index 54% rename from docs/4dbcf072.ac2f7683.js rename to docs/4dbcf072.42badb24.js index d1d6526eb16..16c152479a5 100644 --- a/docs/4dbcf072.ac2f7683.js +++ b/docs/4dbcf072.42badb24.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[28],{138:function(e,n,t){"use strict";t.d(n,"a",(function(){return d})),t.d(n,"b",(function(){return u}));var a=t(0),r=t.n(a);function c(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 b(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=r.a.createContext({}),l=function(e){var n=r.a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):b(b({},n),e)),t},d=function(e){var n=l(e.components);return r.a.createElement(s.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.a.createElement(r.a.Fragment,{},n)}},m=r.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,c=e.originalType,i=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),d=l(t),m=a,u=d["".concat(i,".").concat(m)]||d[m]||p[m]||c;return t?r.a.createElement(u,b(b({ref:n},s),{},{components:t})):r.a.createElement(u,b({ref:n},s))}));function u(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var c=t.length,i=new Array(c);i[0]=m;var b={};for(var o in n)hasOwnProperty.call(n,o)&&(b[o]=n[o]);b.originalType=e,b.mdxType="string"==typeof e?e:a,i[1]=b;for(var s=2;sfunction(e,n,t,{forcePrependBaseUrl:a=!1,absolute:c=!1}={}){if(!t)return t;if(t.startsWith("#"))return t;if(Object(r.b)(t))return t;if(a)return n+t;const i=t.startsWith(n)?t:n+t.replace(/^\//,"");return c?e+i:i}(n,e,t,a)}}function i(e,n={}){const{withBaseUrl:t}=c();return t(e,n)}},141:function(e,n,t){"use strict";function a(e){return!0===/^(\w*:|\/\/)/.test(e)}function r(e){return void 0!==e&&!a(e)}t.d(n,"b",(function(){return a})),t.d(n,"a",(function(){return r}))},83:function(e,n,t){"use strict";t.r(n),t.d(n,"frontMatter",(function(){return b})),t.d(n,"metadata",(function(){return o})),t.d(n,"rightToc",(function(){return s})),t.d(n,"default",(function(){return d}));var a=t(2),r=t(6),c=(t(0),t(138)),i=t(140),b={id:"dbcontext-read-write",title:"9.26 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236",sidebar_label:"9.26 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236"},o={unversionedId:"dbcontext-read-write",id:"dbcontext-read-write",isDocsHomePage:!1,title:"9.26 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236",description:"9.26.1 \u8bfb\u5199\u5206\u79bb",source:"@site/docs\\dbcontext-read-write.mdx",slug:"/dbcontext-read-write",permalink:"/docs/dbcontext-read-write",editUrl:"https://gitee.com/monksoul/Fur/tree/main/handbook/docs/dbcontext-read-write.mdx",version:"current",sidebar_label:"9.26 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236",sidebar:"docs",previous:{title:"9.25 \u4e8b\u52a1\u548c\u5de5\u4f5c\u5355\u5143",permalink:"/docs/tran"},next:{title:"9.27 \u5206\u8868\u5206\u5e93",permalink:"/docs/split-db"}},s=[{value:"9.26.1 \u8bfb\u5199\u5206\u79bb",id:"9261-\u8bfb\u5199\u5206\u79bb",children:[{value:"9.26.1.1 \u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898",id:"92611-\u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898",children:[]},{value:"9.26.1.2 \u6ce8\u610f\u4e8b\u9879",id:"92612-\u6ce8\u610f\u4e8b\u9879",children:[]}]},{value:"9.26.2 \u5982\u4f55\u5b9e\u73b0",id:"9262-\u5982\u4f55\u5b9e\u73b0",children:[{value:"9.26.2.1 \u521b\u5efa \u4e3b\u5e93 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"92621-\u521b\u5efa-\u4e3b\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"9.26.2.2 \u521b\u5efa \u4ece\u5e93 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"92622-\u521b\u5efa-\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"9.26.2.3 \u6ce8\u518c \u4e3b\u4ece\u5e93 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"92623-\u6ce8\u518c-\u4e3b\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"9.26.2.4 \u521b\u5efa Person \u5b9e\u4f53",id:"92624-\u521b\u5efa-person-\u5b9e\u4f53",children:[]},{value:"9.26.2.5 \u5c06 Person \u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868",id:"92625-\u5c06-person-\u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868",children:[]},{value:"9.26.2.6 \u4f7f\u7528\u4f8b\u5b50",id:"92626-\u4f7f\u7528\u4f8b\u5b50",children:[]}]},{value:"9.26.3 \u4e3b\u4ece\u590d\u5236",id:"9263-\u4e3b\u4ece\u590d\u5236",children:[]},{value:"9.26.4 \u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f",id:"9264-\u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f",children:[{value:"9.26.4.1 \u540c\u6b65\u590d\u5236",id:"92641-\u540c\u6b65\u590d\u5236",children:[]},{value:"9.26.4.2 \u5f02\u6b65\u590d\u5236",id:"92642-\u5f02\u6b65\u590d\u5236",children:[]},{value:"9.26.4.3 \u534a\u540c\u6b65\u590d\u5236",id:"92643-\u534a\u540c\u6b65\u590d\u5236",children:[]}]},{value:"9.26.5 SqlServer \u4e3b\u5e93\u914d\u7f6e",id:"9265-sqlserver-\u4e3b\u5e93\u914d\u7f6e",children:[{value:"9.26.5.1 \u6dfb\u52a0 \u672c\u5730\u53d1\u5e03",id:"92651-\u6dfb\u52a0-\u672c\u5730\u53d1\u5e03",children:[]},{value:"9.26.5.2 \u9009\u62e9 \u5206\u53d1\u670d\u52a1\u5668",id:"92652-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668",children:[]},{value:"9.26.5.3 \u542f\u7528 \u4ee3\u7406",id:"92653-\u542f\u7528-\u4ee3\u7406",children:[]},{value:"9.26.5.4 \u53d1\u5e03\u6570\u636e\u5e93",id:"92654-\u53d1\u5e03\u6570\u636e\u5e93",children:[]},{value:"9.26.5.5 \u5feb\u7167\u53d1\u5e03",id:"92655-\u5feb\u7167\u53d1\u5e03",children:[]},{value:"9.26.5.6 \u9009\u62e9\u53d1\u5e03\u9879\u76ee",id:"92656-\u9009\u62e9\u53d1\u5e03\u9879\u76ee",children:[]},{value:"9.26.5.7 \u914d\u7f6e\u5206\u53d1\u8ba1\u5212",id:"92657-\u914d\u7f6e\u5206\u53d1\u8ba1\u5212",children:[]},{value:"9.26.5.8 \u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e",id:"92658-\u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e",children:[]},{value:"9.26.5.9 \u5b8c\u6210\u914d\u7f6e",id:"92659-\u5b8c\u6210\u914d\u7f6e",children:[]}]},{value:"9.26.6 SqlServer \u4ece\u5e93\u914d\u7f6e",id:"9266-sqlserver-\u4ece\u5e93\u914d\u7f6e",children:[{value:"9.26.6.1 \u6dfb\u52a0 \u672c\u5730\u8ba2\u9605",id:"92661-\u6dfb\u52a0-\u672c\u5730\u8ba2\u9605",children:[]},{value:"9.26.6.2 \u9009\u62e9 \u5206\u53d1\u670d\u52a1\u5668",id:"92662-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668",children:[]},{value:"9.26.6.3 \u9009\u62e9 \u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e",id:"92663-\u9009\u62e9-\u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e",children:[]},{value:"9.26.6.4 \u9009\u62e9 \u8ba2\u9605\u6570\u636e\u5e93",id:"92664-\u9009\u62e9-\u8ba2\u9605\u6570\u636e\u5e93",children:[]},{value:"9.26.6.5 \u9009\u62e9 \u5206\u53d1\u5b89\u5168\u8bbe\u7f6e",id:"92665-\u9009\u62e9-\u5206\u53d1\u5b89\u5168\u8bbe\u7f6e",children:[]},{value:"9.26.6.6 \u9009\u62e9 \u540c\u6b65\u8ba1\u5212",id:"92666-\u9009\u62e9-\u540c\u6b65\u8ba1\u5212",children:[]},{value:"9.26.6.7 \u5b8c\u6210\u8ba2\u9605",id:"92667-\u5b8c\u6210\u8ba2\u9605",children:[]}]},{value:"9.26.7 \u5206\u53d1\u5b9a\u4e49\u76d1\u89c6",id:"9267-\u5206\u53d1\u5b9a\u4e49\u76d1\u89c6",children:[]},{value:"9.26.8 \u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c",id:"9268-\u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c",children:[]},{value:"9.26.9 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9269-\u53cd\u9988\u4e0e\u5efa\u8bae",children:[]}],l={rightToc:s};function d(e){var n=e.components,t=Object(r.a)(e,["components"]);return Object(c.b)("wrapper",Object(a.a)({},l,t,{components:n,mdxType:"MDXLayout"}),Object(c.b)("h2",{id:"9261-\u8bfb\u5199\u5206\u79bb"},"9.26.1 \u8bfb\u5199\u5206\u79bb"),Object(c.b)("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"),Object(c.b)("img",{src:Object(i.a)("img/readwrite.png"),style:{height:300}}),Object(c.b)("h3",{id:"92611-\u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898"},"9.26.1.1 \u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898"),Object(c.b)("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"),Object(c.b)("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"),Object(c.b)("h3",{id:"92612-\u6ce8\u610f\u4e8b\u9879"},"9.26.1.2 \u6ce8\u610f\u4e8b\u9879"),Object(c.b)("ul",null,Object(c.b)("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"),Object(c.b)("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"),Object(c.b)("li",{parentName:"ul"},"\u4e3b\u4ece\u7684\u4e00\u81f4\u6027\u95ee\u9898\u9700\u8981\u8003\u8651\u3002")),Object(c.b)("h2",{id:"9262-\u5982\u4f55\u5b9e\u73b0"},"9.26.2 \u5982\u4f55\u5b9e\u73b0"),Object(c.b)("p",null,Object(c.b)("inlineCode",{parentName:"p"},"Fur")," \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"),Object(c.b)("p",null,"\u8bfb\u5199\u5206\u79bb\u64cd\u4f5c\u4e3b\u8981\u4f7f\u7528 ",Object(c.b)("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"),Object(c.b)("p",null,"\u4e0b\u9762\u5c31\u7ed9\u5927\u5bb6\u6f14\u793a\u5982\u4f55\u8bfb\u5199\u591a\u5e93\u8bfb\u5199\u64cd\u4f5c\u3002"),Object(c.b)("h3",{id:"92621-\u521b\u5efa-\u4e3b\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.26.2.1 \u521b\u5efa ",Object(c.b)("inlineCode",{parentName:"h3"},"\u4e3b\u5e93")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.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')),Object(c.b)("p",null,Object(c.b)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff1a")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-json"}),'{\n "ConnectionStrings": {\n "MasterConnectionString": "Server=localhost;Database=Fur;User=sa;Password=000000;MultipleActiveResultSets=True;"\n }\n}\n')),Object(c.b)("h3",{id:"92622-\u521b\u5efa-\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.26.2.2 \u521b\u5efa ",Object(c.b)("inlineCode",{parentName:"h3"},"\u4ece\u5e93")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{11}","{11}":!0}),'using Fur.Core;\nusing Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.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')),Object(c.b)("div",{className:"admonition admonition-important alert alert--info"},Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(c.b)("h5",{parentName:"div"},Object(c.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(c.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(c.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(c.b)("p",{parentName:"div"},"\u591a\u6570\u636e\u5e93\u64cd\u4f5c\u9664\u4e86\u9ed8\u8ba4\u6570\u636e\u5e93\u65e0\u9700\u81ea\u5b9a\u4e49 ",Object(c.b)("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 ",Object(c.b)("inlineCode",{parentName:"p"},"SlaveDbContextLocator")))),Object(c.b)("p",null,Object(c.b)("strong",{parentName:"p"},"\u4ece\u5e93\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\uff1a")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{8}","{8}":!0}),"using Fur.DatabaseAccessor;\n\nnamespace Fur.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")),Object(c.b)("p",null,Object(c.b)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff1a")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-json"}),'{\n "ConnectionStrings": {\n "SlaveConnectionString": "Server=localhost;Database=FurSlave;User=sa;Password=000000;MultipleActiveResultSets=True;"\n }\n}\n')),Object(c.b)("h3",{id:"92623-\u6ce8\u518c-\u4e3b\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.26.2.3 \u6ce8\u518c ",Object(c.b)("inlineCode",{parentName:"h3"},"\u4e3b\u4ece\u5e93")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{13-14}","{13-14}":!0}),"using Fur.Core;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.EntityFramework.Core\n{\n [Startup(600)]\n public sealed class FurEntityFrameworkCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddDatabaseAccessor(options =>\n {\n services.AddSqlServerPool();\n services.AddSqlServerPool();\n });\n }\n }\n}\n")),Object(c.b)("h3",{id:"92624-\u521b\u5efa-person-\u5b9e\u4f53"},"9.26.2.4 \u521b\u5efa ",Object(c.b)("inlineCode",{parentName:"h3"},"Person")," \u5b9e\u4f53"),Object(c.b)("p",null,"\u7531\u4e8e ",Object(c.b)("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 ",Object(c.b)("inlineCode",{parentName:"p"},"\u4e3b\u4ece\u5e93"),"\uff1a"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{7}","{7}":!0}),"using Fur.DatabaseAccessor;\nusing System.ComponentModel.DataAnnotations;\nusing System.ComponentModel.DataAnnotations.Schema;\n\nnamespace Fur.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")),Object(c.b)("h3",{id:"92625-\u5c06-person-\u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868"},"9.26.2.5 \u5c06 ",Object(c.b)("inlineCode",{parentName:"h3"},"Person")," \u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868"),Object(c.b)("p",null,Object(c.b)("strong",{parentName:"p"},"\u521b\u5efa\u4e3b\u5e93\u6570\u636e\u5e93\u8868\uff1a")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Add-Migration v0.0.1 -Context MasterDbContext\n")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Update-Database -Context MasterDbContext\n")),Object(c.b)("p",null,Object(c.b)("strong",{parentName:"p"},"\u521b\u5efa\u4ece\u5e93\u6570\u636e\u5e93\u8868\uff1a")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Add-Migration v0.0.1 -Context SlaveDbContext\n")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Update-Database -Context SlaveDbContext\n")),Object(c.b)("img",{src:Object(i.a)("img/readwrite1.png")}),Object(c.b)("img",{src:Object(i.a)("img/readwrite2.png")}),Object(c.b)("h3",{id:"92626-\u4f7f\u7528\u4f8b\u5b50"},"9.26.2.6 \u4f7f\u7528\u4f8b\u5b50"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{13,19,31,40}","{13,19,31,40}":!0}),'using Fur.Core;\nusing Fur.DatabaseAccessor;\nusing Fur.DynamicApiController;\nusing System.Collections.Generic;\n\nnamespace Fur.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();\n }\n }\n}\n')),Object(c.b)("h2",{id:"9263-\u4e3b\u4ece\u590d\u5236"},"9.26.3 \u4e3b\u4ece\u590d\u5236"),Object(c.b)("p",null,"\u4e3b\u4ece\u590d\u5236\uff1a\u662f\u4e00\u79cd\u6570\u636e\u5907\u4efd\u7684\u65b9\u6848\u3002"),Object(c.b)("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",Object(c.b)("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")),Object(c.b)("h2",{id:"9264-\u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f"},"9.26.4 \u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f"),Object(c.b)("h3",{id:"92641-\u540c\u6b65\u590d\u5236"},"9.26.4.1 \u540c\u6b65\u590d\u5236"),Object(c.b)("p",null,"\u6240\u8c13\u7684\u540c\u6b65\u590d\u5236\uff0c\u610f\u601d\u662f ",Object(c.b)("inlineCode",{parentName:"p"},"Master")," \u7684\u53d8\u5316\uff0c\u5fc5\u987b\u7b49\u5f85 ",Object(c.b)("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 ",Object(c.b)("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"),Object(c.b)("h3",{id:"92642-\u5f02\u6b65\u590d\u5236"},"9.26.4.2 \u5f02\u6b65\u590d\u5236"),Object(c.b)("p",null,"\u5982\u540c AJAX \u8bf7\u6c42\u4e00\u6837\u3002",Object(c.b)("inlineCode",{parentName:"p"},"Master")," \u53ea\u9700\u8981\u5b8c\u6210\u81ea\u5df1\u7684\u6570\u636e\u5e93\u64cd\u4f5c\u5373\u53ef\u3002\u81f3\u4e8e ",Object(c.b)("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",Object(c.b)("strong",{parentName:"p"},"\uff08\u63a8\u8350\u65b9\u5f0f\uff09")),Object(c.b)("h3",{id:"92643-\u534a\u540c\u6b65\u590d\u5236"},"9.26.4.3 \u534a\u540c\u6b65\u590d\u5236"),Object(c.b)("p",null,Object(c.b)("inlineCode",{parentName:"p"},"Master")," \u53ea\u4fdd\u8bc1 ",Object(c.b)("inlineCode",{parentName:"p"},"Slaves")," \u4e2d\u7684\u4e00\u4e2a\u64cd\u4f5c\u6210\u529f\uff0c\u5c31\u8fd4\u56de\uff0c\u5176\u4ed6 ",Object(c.b)("inlineCode",{parentName:"p"},"Slave")," \u4e0d\u7ba1\u3002"),Object(c.b)("p",null,"\u4e0b\u9762\u5c06\u4f7f\u7528 ",Object(c.b)("inlineCode",{parentName:"p"},"SqlServer")," \u7b80\u5355\u914d\u7f6e\u4e3b\u4ece\u590d\u5236\u529f\u80fd\u3002"),Object(c.b)("h2",{id:"9265-sqlserver-\u4e3b\u5e93\u914d\u7f6e"},"9.26.5 ",Object(c.b)("inlineCode",{parentName:"h2"},"SqlServer")," \u4e3b\u5e93\u914d\u7f6e"),Object(c.b)("h3",{id:"92651-\u6dfb\u52a0-\u672c\u5730\u53d1\u5e03"},"9.26.5.1 \u6dfb\u52a0 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u672c\u5730\u53d1\u5e03")),Object(c.b)("img",{src:Object(i.a)("img/dbcopy1.png")}),Object(c.b)("h3",{id:"92652-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668"},"9.26.5.2 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u670d\u52a1\u5668")),Object(c.b)("img",{src:Object(i.a)("img/dbcopy2.png")}),Object(c.b)("h3",{id:"92653-\u542f\u7528-\u4ee3\u7406"},"9.26.5.3 \u542f\u7528 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u4ee3\u7406")),Object(c.b)("img",{src:Object(i.a)("img/dbcopy3.png")}),Object(c.b)("h3",{id:"92654-\u53d1\u5e03\u6570\u636e\u5e93"},"9.26.5.4 \u53d1\u5e03\u6570\u636e\u5e93"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy4.png")}),Object(c.b)("h3",{id:"92655-\u5feb\u7167\u53d1\u5e03"},"9.26.5.5 \u5feb\u7167\u53d1\u5e03"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy5.png")}),Object(c.b)("p",null,"\u5177\u4f53\u9009\u62e9\u4f55\u79cd\u53d1\u5e03\u7c7b\u578b\uff0c\u89c6\u5177\u4f53\u4e1a\u52a1\u573a\u666f\u800c\u5b9a\u3002"),Object(c.b)("h3",{id:"92656-\u9009\u62e9\u53d1\u5e03\u9879\u76ee"},"9.26.5.6 \u9009\u62e9\u53d1\u5e03\u9879\u76ee"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy6.png")}),Object(c.b)("h3",{id:"92657-\u914d\u7f6e\u5206\u53d1\u8ba1\u5212"},"9.26.5.7 \u914d\u7f6e\u5206\u53d1\u8ba1\u5212"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy7.png")}),Object(c.b)("img",{src:Object(i.a)("img/dbcopy8.png")}),Object(c.b)("h3",{id:"92658-\u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e"},"9.26.5.8 \u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy9.png")}),Object(c.b)("img",{src:Object(i.a)("img/dbcopy10.png")}),Object(c.b)("h3",{id:"92659-\u5b8c\u6210\u914d\u7f6e"},"9.26.5.9 \u5b8c\u6210\u914d\u7f6e"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy11.png")}),Object(c.b)("img",{src:Object(i.a)("img/dbcopy12.png")}),Object(c.b)("h2",{id:"9266-sqlserver-\u4ece\u5e93\u914d\u7f6e"},"9.26.6 ",Object(c.b)("inlineCode",{parentName:"h2"},"SqlServer")," \u4ece\u5e93\u914d\u7f6e"),Object(c.b)("h3",{id:"92661-\u6dfb\u52a0-\u672c\u5730\u8ba2\u9605"},"9.26.6.1 \u6dfb\u52a0 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u672c\u5730\u8ba2\u9605")),Object(c.b)("img",{src:Object(i.a)("img/dbrece1.png")}),Object(c.b)("h3",{id:"92662-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668"},"9.26.6.2 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u670d\u52a1\u5668")),Object(c.b)("img",{src:Object(i.a)("img/dbrece2.png")}),Object(c.b)("h3",{id:"92663-\u9009\u62e9-\u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e"},"9.26.6.3 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e")),Object(c.b)("img",{src:Object(i.a)("img/dbrece3.png")}),Object(c.b)("h3",{id:"92664-\u9009\u62e9-\u8ba2\u9605\u6570\u636e\u5e93"},"9.26.6.4 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u8ba2\u9605\u6570\u636e\u5e93")),Object(c.b)("img",{src:Object(i.a)("img/dbrece4.png")}),Object(c.b)("h3",{id:"92665-\u9009\u62e9-\u5206\u53d1\u5b89\u5168\u8bbe\u7f6e"},"9.26.6.5 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u5b89\u5168\u8bbe\u7f6e")),Object(c.b)("img",{src:Object(i.a)("img/dbrece5.png")}),Object(c.b)("img",{src:Object(i.a)("img/dbrece6.png")}),Object(c.b)("h3",{id:"92666-\u9009\u62e9-\u540c\u6b65\u8ba1\u5212"},"9.26.6.6 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u540c\u6b65\u8ba1\u5212")),Object(c.b)("img",{src:Object(i.a)("img/dbrece7.png")}),Object(c.b)("h3",{id:"92667-\u5b8c\u6210\u8ba2\u9605"},"9.26.6.7 \u5b8c\u6210\u8ba2\u9605"),Object(c.b)("img",{src:Object(i.a)("img/dbrece8.png")}),Object(c.b)("h2",{id:"9267-\u5206\u53d1\u5b9a\u4e49\u76d1\u89c6"},"9.26.7 \u5206\u53d1\u5b9a\u4e49\u76d1\u89c6"),Object(c.b)("img",{src:Object(i.a)("img/dbrece9.png")}),Object(c.b)("h2",{id:"9268-\u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c"},"9.26.8 \u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c"),Object(c.b)("img",{src:Object(i.a)("img/dbrece10.png")}),Object(c.b)("img",{src:Object(i.a)("img/dbrece11.png")}),Object(c.b)("div",{className:"admonition admonition-important alert alert--info"},Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(c.b)("h5",{parentName:"div"},Object(c.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(c.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(c.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u7279\u6027")),Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(c.b)("p",{parentName:"div"},'\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'))),Object(c.b)("h2",{id:"9269-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.26.9 \u53cd\u9988\u4e0e\u5efa\u8bae"),Object(c.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(c.b)("h5",{parentName:"div"},Object(c.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(c.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(c.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e0e\u6211\u4eec\u4ea4\u6d41")),Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(c.b)("p",{parentName:"div"},"\u7ed9 Fur \u63d0 ",Object(c.b)("a",Object(a.a)({parentName:"p"},{href:"https://gitee.com/monksoul/Fur/issues/new?issue"}),"Issue"),"\u3002"))))}d.isMDXComponent=!0}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[28],{138:function(e,n,t){"use strict";t.d(n,"a",(function(){return d})),t.d(n,"b",(function(){return u}));var a=t(0),r=t.n(a);function c(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 b(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=r.a.createContext({}),l=function(e){var n=r.a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):b(b({},n),e)),t},d=function(e){var n=l(e.components);return r.a.createElement(s.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.a.createElement(r.a.Fragment,{},n)}},m=r.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,c=e.originalType,i=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),d=l(t),m=a,u=d["".concat(i,".").concat(m)]||d[m]||p[m]||c;return t?r.a.createElement(u,b(b({ref:n},s),{},{components:t})):r.a.createElement(u,b({ref:n},s))}));function u(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var c=t.length,i=new Array(c);i[0]=m;var b={};for(var o in n)hasOwnProperty.call(n,o)&&(b[o]=n[o]);b.originalType=e,b.mdxType="string"==typeof e?e:a,i[1]=b;for(var s=2;sfunction(e,n,t,{forcePrependBaseUrl:a=!1,absolute:c=!1}={}){if(!t)return t;if(t.startsWith("#"))return t;if(Object(r.b)(t))return t;if(a)return n+t;const i=t.startsWith(n)?t:n+t.replace(/^\//,"");return c?e+i:i}(n,e,t,a)}}function i(e,n={}){const{withBaseUrl:t}=c();return t(e,n)}},141:function(e,n,t){"use strict";function a(e){return!0===/^(\w*:|\/\/)/.test(e)}function r(e){return void 0!==e&&!a(e)}t.d(n,"b",(function(){return a})),t.d(n,"a",(function(){return r}))},83:function(e,n,t){"use strict";t.r(n),t.d(n,"frontMatter",(function(){return b})),t.d(n,"metadata",(function(){return o})),t.d(n,"rightToc",(function(){return s})),t.d(n,"default",(function(){return d}));var a=t(2),r=t(6),c=(t(0),t(138)),i=t(140),b={id:"dbcontext-read-write",title:"9.26 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236",sidebar_label:"9.26 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236"},o={unversionedId:"dbcontext-read-write",id:"dbcontext-read-write",isDocsHomePage:!1,title:"9.26 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236",description:"9.26.1 \u8bfb\u5199\u5206\u79bb",source:"@site/docs\\dbcontext-read-write.mdx",slug:"/dbcontext-read-write",permalink:"/docs/dbcontext-read-write",editUrl:"https://gitee.com/monksoul/Fur/tree/main/handbook/docs/dbcontext-read-write.mdx",version:"current",sidebar_label:"9.26 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236",sidebar:"docs",previous:{title:"9.25 \u4e8b\u52a1\u548c\u5de5\u4f5c\u5355\u5143",permalink:"/docs/tran"},next:{title:"9.27 \u5206\u8868\u5206\u5e93",permalink:"/docs/split-db"}},s=[{value:"9.26.1 \u8bfb\u5199\u5206\u79bb",id:"9261-\u8bfb\u5199\u5206\u79bb",children:[{value:"9.26.1.1 \u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898",id:"92611-\u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898",children:[]},{value:"9.26.1.2 \u6ce8\u610f\u4e8b\u9879",id:"92612-\u6ce8\u610f\u4e8b\u9879",children:[]}]},{value:"9.26.2 \u5982\u4f55\u5b9e\u73b0",id:"9262-\u5982\u4f55\u5b9e\u73b0",children:[{value:"9.26.2.1 \u521b\u5efa \u4e3b\u5e93 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"92621-\u521b\u5efa-\u4e3b\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"9.26.2.2 \u521b\u5efa \u4ece\u5e93 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"92622-\u521b\u5efa-\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"9.26.2.3 \u6ce8\u518c \u4e3b\u4ece\u5e93 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"92623-\u6ce8\u518c-\u4e3b\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"9.26.2.4 \u521b\u5efa Person \u5b9e\u4f53",id:"92624-\u521b\u5efa-person-\u5b9e\u4f53",children:[]},{value:"9.26.2.5 \u5c06 Person \u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868",id:"92625-\u5c06-person-\u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868",children:[]},{value:"9.26.2.6 \u4f7f\u7528\u4f8b\u5b50",id:"92626-\u4f7f\u7528\u4f8b\u5b50",children:[]}]},{value:"9.26.3 \u4e3b\u4ece\u590d\u5236",id:"9263-\u4e3b\u4ece\u590d\u5236",children:[]},{value:"9.26.4 \u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f",id:"9264-\u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f",children:[{value:"9.26.4.1 \u540c\u6b65\u590d\u5236",id:"92641-\u540c\u6b65\u590d\u5236",children:[]},{value:"9.26.4.2 \u5f02\u6b65\u590d\u5236",id:"92642-\u5f02\u6b65\u590d\u5236",children:[]},{value:"9.26.4.3 \u534a\u540c\u6b65\u590d\u5236",id:"92643-\u534a\u540c\u6b65\u590d\u5236",children:[]}]},{value:"9.26.5 SqlServer \u4e3b\u5e93\u914d\u7f6e",id:"9265-sqlserver-\u4e3b\u5e93\u914d\u7f6e",children:[{value:"9.26.5.1 \u6dfb\u52a0 \u672c\u5730\u53d1\u5e03",id:"92651-\u6dfb\u52a0-\u672c\u5730\u53d1\u5e03",children:[]},{value:"9.26.5.2 \u9009\u62e9 \u5206\u53d1\u670d\u52a1\u5668",id:"92652-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668",children:[]},{value:"9.26.5.3 \u542f\u7528 \u4ee3\u7406",id:"92653-\u542f\u7528-\u4ee3\u7406",children:[]},{value:"9.26.5.4 \u53d1\u5e03\u6570\u636e\u5e93",id:"92654-\u53d1\u5e03\u6570\u636e\u5e93",children:[]},{value:"9.26.5.5 \u5feb\u7167\u53d1\u5e03",id:"92655-\u5feb\u7167\u53d1\u5e03",children:[]},{value:"9.26.5.6 \u9009\u62e9\u53d1\u5e03\u9879\u76ee",id:"92656-\u9009\u62e9\u53d1\u5e03\u9879\u76ee",children:[]},{value:"9.26.5.7 \u914d\u7f6e\u5206\u53d1\u8ba1\u5212",id:"92657-\u914d\u7f6e\u5206\u53d1\u8ba1\u5212",children:[]},{value:"9.26.5.8 \u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e",id:"92658-\u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e",children:[]},{value:"9.26.5.9 \u5b8c\u6210\u914d\u7f6e",id:"92659-\u5b8c\u6210\u914d\u7f6e",children:[]}]},{value:"9.26.6 SqlServer \u4ece\u5e93\u914d\u7f6e",id:"9266-sqlserver-\u4ece\u5e93\u914d\u7f6e",children:[{value:"9.26.6.1 \u6dfb\u52a0 \u672c\u5730\u8ba2\u9605",id:"92661-\u6dfb\u52a0-\u672c\u5730\u8ba2\u9605",children:[]},{value:"9.26.6.2 \u9009\u62e9 \u5206\u53d1\u670d\u52a1\u5668",id:"92662-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668",children:[]},{value:"9.26.6.3 \u9009\u62e9 \u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e",id:"92663-\u9009\u62e9-\u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e",children:[]},{value:"9.26.6.4 \u9009\u62e9 \u8ba2\u9605\u6570\u636e\u5e93",id:"92664-\u9009\u62e9-\u8ba2\u9605\u6570\u636e\u5e93",children:[]},{value:"9.26.6.5 \u9009\u62e9 \u5206\u53d1\u5b89\u5168\u8bbe\u7f6e",id:"92665-\u9009\u62e9-\u5206\u53d1\u5b89\u5168\u8bbe\u7f6e",children:[]},{value:"9.26.6.6 \u9009\u62e9 \u540c\u6b65\u8ba1\u5212",id:"92666-\u9009\u62e9-\u540c\u6b65\u8ba1\u5212",children:[]},{value:"9.26.6.7 \u5b8c\u6210\u8ba2\u9605",id:"92667-\u5b8c\u6210\u8ba2\u9605",children:[]}]},{value:"9.26.7 \u5206\u53d1\u5b9a\u4e49\u76d1\u89c6",id:"9267-\u5206\u53d1\u5b9a\u4e49\u76d1\u89c6",children:[]},{value:"9.26.8 \u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c",id:"9268-\u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c",children:[]},{value:"9.26.9 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9269-\u53cd\u9988\u4e0e\u5efa\u8bae",children:[]}],l={rightToc:s};function d(e){var n=e.components,t=Object(r.a)(e,["components"]);return Object(c.b)("wrapper",Object(a.a)({},l,t,{components:n,mdxType:"MDXLayout"}),Object(c.b)("h2",{id:"9261-\u8bfb\u5199\u5206\u79bb"},"9.26.1 \u8bfb\u5199\u5206\u79bb"),Object(c.b)("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"),Object(c.b)("img",{src:Object(i.a)("img/readwrite.png"),style:{height:300}}),Object(c.b)("h3",{id:"92611-\u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898"},"9.26.1.1 \u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898"),Object(c.b)("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"),Object(c.b)("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"),Object(c.b)("h3",{id:"92612-\u6ce8\u610f\u4e8b\u9879"},"9.26.1.2 \u6ce8\u610f\u4e8b\u9879"),Object(c.b)("ul",null,Object(c.b)("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"),Object(c.b)("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"),Object(c.b)("li",{parentName:"ul"},"\u4e3b\u4ece\u7684\u4e00\u81f4\u6027\u95ee\u9898\u9700\u8981\u8003\u8651\u3002")),Object(c.b)("h2",{id:"9262-\u5982\u4f55\u5b9e\u73b0"},"9.26.2 \u5982\u4f55\u5b9e\u73b0"),Object(c.b)("p",null,Object(c.b)("inlineCode",{parentName:"p"},"Fur")," \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"),Object(c.b)("p",null,"\u8bfb\u5199\u5206\u79bb\u64cd\u4f5c\u4e3b\u8981\u4f7f\u7528 ",Object(c.b)("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"),Object(c.b)("p",null,"\u4e0b\u9762\u5c31\u7ed9\u5927\u5bb6\u6f14\u793a\u5982\u4f55\u8bfb\u5199\u591a\u5e93\u8bfb\u5199\u64cd\u4f5c\u3002"),Object(c.b)("h3",{id:"92621-\u521b\u5efa-\u4e3b\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.26.2.1 \u521b\u5efa ",Object(c.b)("inlineCode",{parentName:"h3"},"\u4e3b\u5e93")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.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')),Object(c.b)("p",null,Object(c.b)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff1a")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-json"}),'{\n "ConnectionStrings": {\n "MasterConnectionString": "Server=localhost;Database=Fur;User=sa;Password=000000;MultipleActiveResultSets=True;"\n }\n}\n')),Object(c.b)("h3",{id:"92622-\u521b\u5efa-\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.26.2.2 \u521b\u5efa ",Object(c.b)("inlineCode",{parentName:"h3"},"\u4ece\u5e93")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{11}","{11}":!0}),'using Fur.Core;\nusing Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.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')),Object(c.b)("div",{className:"admonition admonition-important alert alert--info"},Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(c.b)("h5",{parentName:"div"},Object(c.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(c.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(c.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(c.b)("p",{parentName:"div"},"\u591a\u6570\u636e\u5e93\u64cd\u4f5c\u9664\u4e86\u9ed8\u8ba4\u6570\u636e\u5e93\u65e0\u9700\u81ea\u5b9a\u4e49 ",Object(c.b)("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 ",Object(c.b)("inlineCode",{parentName:"p"},"SlaveDbContextLocator")))),Object(c.b)("p",null,Object(c.b)("strong",{parentName:"p"},"\u4ece\u5e93\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\uff1a")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{8}","{8}":!0}),"using Fur.DatabaseAccessor;\n\nnamespace Fur.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")),Object(c.b)("p",null,Object(c.b)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff1a")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-json"}),'{\n "ConnectionStrings": {\n "SlaveConnectionString": "Server=localhost;Database=FurSlave;User=sa;Password=000000;MultipleActiveResultSets=True;"\n }\n}\n')),Object(c.b)("h3",{id:"92623-\u6ce8\u518c-\u4e3b\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.26.2.3 \u6ce8\u518c ",Object(c.b)("inlineCode",{parentName:"h3"},"\u4e3b\u4ece\u5e93")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{13-14}","{13-14}":!0}),"using Fur.Core;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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.AddSqlServerPool();\n services.AddSqlServerPool();\n });\n }\n }\n}\n")),Object(c.b)("h3",{id:"92624-\u521b\u5efa-person-\u5b9e\u4f53"},"9.26.2.4 \u521b\u5efa ",Object(c.b)("inlineCode",{parentName:"h3"},"Person")," \u5b9e\u4f53"),Object(c.b)("p",null,"\u7531\u4e8e ",Object(c.b)("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 ",Object(c.b)("inlineCode",{parentName:"p"},"\u4e3b\u4ece\u5e93"),"\uff1a"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{7}","{7}":!0}),"using Fur.DatabaseAccessor;\nusing System.ComponentModel.DataAnnotations;\nusing System.ComponentModel.DataAnnotations.Schema;\n\nnamespace Fur.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")),Object(c.b)("h3",{id:"92625-\u5c06-person-\u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868"},"9.26.2.5 \u5c06 ",Object(c.b)("inlineCode",{parentName:"h3"},"Person")," \u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868"),Object(c.b)("p",null,Object(c.b)("strong",{parentName:"p"},"\u521b\u5efa\u4e3b\u5e93\u6570\u636e\u5e93\u8868\uff1a")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Add-Migration v0.0.1 -Context MasterDbContext\n")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Update-Database -Context MasterDbContext\n")),Object(c.b)("p",null,Object(c.b)("strong",{parentName:"p"},"\u521b\u5efa\u4ece\u5e93\u6570\u636e\u5e93\u8868\uff1a")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Add-Migration v0.0.1 -Context SlaveDbContext\n")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Update-Database -Context SlaveDbContext\n")),Object(c.b)("img",{src:Object(i.a)("img/readwrite1.png")}),Object(c.b)("img",{src:Object(i.a)("img/readwrite2.png")}),Object(c.b)("h3",{id:"92626-\u4f7f\u7528\u4f8b\u5b50"},"9.26.2.6 \u4f7f\u7528\u4f8b\u5b50"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{13,19,31,40}","{13,19,31,40}":!0}),'using Fur.Core;\nusing Fur.DatabaseAccessor;\nusing Fur.DynamicApiController;\nusing System.Collections.Generic;\n\nnamespace Fur.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();\n }\n }\n}\n')),Object(c.b)("h2",{id:"9263-\u4e3b\u4ece\u590d\u5236"},"9.26.3 \u4e3b\u4ece\u590d\u5236"),Object(c.b)("p",null,"\u4e3b\u4ece\u590d\u5236\uff1a\u662f\u4e00\u79cd\u6570\u636e\u5907\u4efd\u7684\u65b9\u6848\u3002"),Object(c.b)("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",Object(c.b)("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")),Object(c.b)("h2",{id:"9264-\u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f"},"9.26.4 \u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f"),Object(c.b)("h3",{id:"92641-\u540c\u6b65\u590d\u5236"},"9.26.4.1 \u540c\u6b65\u590d\u5236"),Object(c.b)("p",null,"\u6240\u8c13\u7684\u540c\u6b65\u590d\u5236\uff0c\u610f\u601d\u662f ",Object(c.b)("inlineCode",{parentName:"p"},"Master")," \u7684\u53d8\u5316\uff0c\u5fc5\u987b\u7b49\u5f85 ",Object(c.b)("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 ",Object(c.b)("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"),Object(c.b)("h3",{id:"92642-\u5f02\u6b65\u590d\u5236"},"9.26.4.2 \u5f02\u6b65\u590d\u5236"),Object(c.b)("p",null,"\u5982\u540c AJAX \u8bf7\u6c42\u4e00\u6837\u3002",Object(c.b)("inlineCode",{parentName:"p"},"Master")," \u53ea\u9700\u8981\u5b8c\u6210\u81ea\u5df1\u7684\u6570\u636e\u5e93\u64cd\u4f5c\u5373\u53ef\u3002\u81f3\u4e8e ",Object(c.b)("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",Object(c.b)("strong",{parentName:"p"},"\uff08\u63a8\u8350\u65b9\u5f0f\uff09")),Object(c.b)("h3",{id:"92643-\u534a\u540c\u6b65\u590d\u5236"},"9.26.4.3 \u534a\u540c\u6b65\u590d\u5236"),Object(c.b)("p",null,Object(c.b)("inlineCode",{parentName:"p"},"Master")," \u53ea\u4fdd\u8bc1 ",Object(c.b)("inlineCode",{parentName:"p"},"Slaves")," \u4e2d\u7684\u4e00\u4e2a\u64cd\u4f5c\u6210\u529f\uff0c\u5c31\u8fd4\u56de\uff0c\u5176\u4ed6 ",Object(c.b)("inlineCode",{parentName:"p"},"Slave")," \u4e0d\u7ba1\u3002"),Object(c.b)("p",null,"\u4e0b\u9762\u5c06\u4f7f\u7528 ",Object(c.b)("inlineCode",{parentName:"p"},"SqlServer")," \u7b80\u5355\u914d\u7f6e\u4e3b\u4ece\u590d\u5236\u529f\u80fd\u3002"),Object(c.b)("h2",{id:"9265-sqlserver-\u4e3b\u5e93\u914d\u7f6e"},"9.26.5 ",Object(c.b)("inlineCode",{parentName:"h2"},"SqlServer")," \u4e3b\u5e93\u914d\u7f6e"),Object(c.b)("h3",{id:"92651-\u6dfb\u52a0-\u672c\u5730\u53d1\u5e03"},"9.26.5.1 \u6dfb\u52a0 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u672c\u5730\u53d1\u5e03")),Object(c.b)("img",{src:Object(i.a)("img/dbcopy1.png")}),Object(c.b)("h3",{id:"92652-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668"},"9.26.5.2 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u670d\u52a1\u5668")),Object(c.b)("img",{src:Object(i.a)("img/dbcopy2.png")}),Object(c.b)("h3",{id:"92653-\u542f\u7528-\u4ee3\u7406"},"9.26.5.3 \u542f\u7528 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u4ee3\u7406")),Object(c.b)("img",{src:Object(i.a)("img/dbcopy3.png")}),Object(c.b)("h3",{id:"92654-\u53d1\u5e03\u6570\u636e\u5e93"},"9.26.5.4 \u53d1\u5e03\u6570\u636e\u5e93"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy4.png")}),Object(c.b)("h3",{id:"92655-\u5feb\u7167\u53d1\u5e03"},"9.26.5.5 \u5feb\u7167\u53d1\u5e03"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy5.png")}),Object(c.b)("p",null,"\u5177\u4f53\u9009\u62e9\u4f55\u79cd\u53d1\u5e03\u7c7b\u578b\uff0c\u89c6\u5177\u4f53\u4e1a\u52a1\u573a\u666f\u800c\u5b9a\u3002"),Object(c.b)("h3",{id:"92656-\u9009\u62e9\u53d1\u5e03\u9879\u76ee"},"9.26.5.6 \u9009\u62e9\u53d1\u5e03\u9879\u76ee"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy6.png")}),Object(c.b)("h3",{id:"92657-\u914d\u7f6e\u5206\u53d1\u8ba1\u5212"},"9.26.5.7 \u914d\u7f6e\u5206\u53d1\u8ba1\u5212"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy7.png")}),Object(c.b)("img",{src:Object(i.a)("img/dbcopy8.png")}),Object(c.b)("h3",{id:"92658-\u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e"},"9.26.5.8 \u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy9.png")}),Object(c.b)("img",{src:Object(i.a)("img/dbcopy10.png")}),Object(c.b)("h3",{id:"92659-\u5b8c\u6210\u914d\u7f6e"},"9.26.5.9 \u5b8c\u6210\u914d\u7f6e"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy11.png")}),Object(c.b)("img",{src:Object(i.a)("img/dbcopy12.png")}),Object(c.b)("h2",{id:"9266-sqlserver-\u4ece\u5e93\u914d\u7f6e"},"9.26.6 ",Object(c.b)("inlineCode",{parentName:"h2"},"SqlServer")," \u4ece\u5e93\u914d\u7f6e"),Object(c.b)("h3",{id:"92661-\u6dfb\u52a0-\u672c\u5730\u8ba2\u9605"},"9.26.6.1 \u6dfb\u52a0 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u672c\u5730\u8ba2\u9605")),Object(c.b)("img",{src:Object(i.a)("img/dbrece1.png")}),Object(c.b)("h3",{id:"92662-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668"},"9.26.6.2 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u670d\u52a1\u5668")),Object(c.b)("img",{src:Object(i.a)("img/dbrece2.png")}),Object(c.b)("h3",{id:"92663-\u9009\u62e9-\u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e"},"9.26.6.3 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e")),Object(c.b)("img",{src:Object(i.a)("img/dbrece3.png")}),Object(c.b)("h3",{id:"92664-\u9009\u62e9-\u8ba2\u9605\u6570\u636e\u5e93"},"9.26.6.4 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u8ba2\u9605\u6570\u636e\u5e93")),Object(c.b)("img",{src:Object(i.a)("img/dbrece4.png")}),Object(c.b)("h3",{id:"92665-\u9009\u62e9-\u5206\u53d1\u5b89\u5168\u8bbe\u7f6e"},"9.26.6.5 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u5b89\u5168\u8bbe\u7f6e")),Object(c.b)("img",{src:Object(i.a)("img/dbrece5.png")}),Object(c.b)("img",{src:Object(i.a)("img/dbrece6.png")}),Object(c.b)("h3",{id:"92666-\u9009\u62e9-\u540c\u6b65\u8ba1\u5212"},"9.26.6.6 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u540c\u6b65\u8ba1\u5212")),Object(c.b)("img",{src:Object(i.a)("img/dbrece7.png")}),Object(c.b)("h3",{id:"92667-\u5b8c\u6210\u8ba2\u9605"},"9.26.6.7 \u5b8c\u6210\u8ba2\u9605"),Object(c.b)("img",{src:Object(i.a)("img/dbrece8.png")}),Object(c.b)("h2",{id:"9267-\u5206\u53d1\u5b9a\u4e49\u76d1\u89c6"},"9.26.7 \u5206\u53d1\u5b9a\u4e49\u76d1\u89c6"),Object(c.b)("img",{src:Object(i.a)("img/dbrece9.png")}),Object(c.b)("h2",{id:"9268-\u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c"},"9.26.8 \u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c"),Object(c.b)("img",{src:Object(i.a)("img/dbrece10.png")}),Object(c.b)("img",{src:Object(i.a)("img/dbrece11.png")}),Object(c.b)("div",{className:"admonition admonition-important alert alert--info"},Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(c.b)("h5",{parentName:"div"},Object(c.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(c.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(c.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u7279\u6027")),Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(c.b)("p",{parentName:"div"},'\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'))),Object(c.b)("h2",{id:"9269-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.26.9 \u53cd\u9988\u4e0e\u5efa\u8bae"),Object(c.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(c.b)("h5",{parentName:"div"},Object(c.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(c.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(c.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e0e\u6211\u4eec\u4ea4\u6d41")),Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(c.b)("p",{parentName:"div"},"\u7ed9 Fur \u63d0 ",Object(c.b)("a",Object(a.a)({parentName:"p"},{href:"https://gitee.com/monksoul/Fur/issues/new?issue"}),"Issue"),"\u3002"))))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/5ce0ebbd.1dfadef3.js b/docs/5ce0ebbd.1dfadef3.js new file mode 100644 index 00000000000..ff4f32806f8 --- /dev/null +++ b/docs/5ce0ebbd.1dfadef3.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[33],{138:function(e,n,t){"use strict";t.d(n,"a",(function(){return s})),t.d(n,"b",(function(){return j}));var a=t(0),r=t.n(a);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 p(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 c(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 b=r.a.createContext({}),l=function(e){var n=r.a.useContext(b),t=n;return e&&(t="function"==typeof e?e(n):c(c({},n),e)),t},s=function(e){var n=l(e.components);return r.a.createElement(b.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.a.createElement(r.a.Fragment,{},n)}},d=r.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,p=e.parentName,b=o(e,["components","mdxType","originalType","parentName"]),s=l(t),d=a,j=s["".concat(p,".").concat(d)]||s[d]||u[d]||i;return t?r.a.createElement(j,c(c({ref:n},b),{},{components:t})):r.a.createElement(j,c({ref:n},b))}));function j(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=t.length,p=new Array(i);p[0]=d;var c={};for(var o in n)hasOwnProperty.call(n,o)&&(c[o]=n[o]);c.originalType=e,c.mdxType="string"==typeof e?e:a,p[1]=c;for(var b=2;bStartup \u7c7b",id:"31-startup-\u7c7b",children:[{value:"3.1.1 Startup \u4e24\u4e2a\u91cd\u8981\u65b9\u6cd5",id:"311-startup-\u4e24\u4e2a\u91cd\u8981\u65b9\u6cd5",children:[]}]},{value:"3.2 AppStartup",id:"32-appstartup",children:[{value:"3.2.1 \u5982\u4f55\u914d\u7f6e AppStartup",id:"321-\u5982\u4f55\u914d\u7f6e-appstartup",children:[]},{value:"3.2.2 AppStartup \u7ea6\u5b9a",id:"322-appstartup-\u7ea6\u5b9a",children:[]},{value:"3.2.3 AppStartup \u914d\u7f6e\u987a\u5e8f",id:"323-appstartup-\u914d\u7f6e\u987a\u5e8f",children:[]},{value:"3.2.4 AppStartup \u65b9\u6cd5\u8c03\u7528\u987a\u5e8f",id:"324-appstartup-\u65b9\u6cd5\u8c03\u7528\u987a\u5e8f",children:[]}]},{value:"3.3 \u6846\u67b6\u9ed8\u8ba4 AppStartup \u5b9e\u73b0",id:"33-\u6846\u67b6\u9ed8\u8ba4-appstartup-\u5b9e\u73b0",children:[]},{value:"3.4 Startup \u914d\u7f6e\u6700\u4f73\u5b9e\u8df5",id:"34-startup-\u914d\u7f6e\u6700\u4f73\u5b9e\u8df5",children:[]},{value:"3.5 \u5173\u4e8e appsettings.json",id:"35-\u5173\u4e8e-appsettingsjson",children:[]},{value:"3.6 \u795e\u5947\u7684 Inject()",id:"36-\u795e\u5947\u7684-inject",children:[]},{value:"3.7 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"37-\u53cd\u9988\u4e0e\u5efa\u8bae",children:[]}],b={rightToc:o};function l(e){var n=e.components,t=Object(r.a)(e,["components"]);return Object(i.b)("wrapper",Object(a.a)({},b,t,{components:n,mdxType:"MDXLayout"}),Object(i.b)("h2",{id:"31-startup-\u7c7b"},"3.1 ",Object(i.b)("inlineCode",{parentName:"h2"},"Startup")," \u7c7b"),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"Startup")," \u7c7b\u662f ",Object(i.b)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u5e94\u7528\u7a0b\u5e8f\u542f\u52a8\u9ed8\u8ba4\u8c03\u7528\u7684\u7c7b\uff0c\u8be5\u7c7b\u662f\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Program.cs")," \u4e2d\u914d\u7f6e\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{19} title="Fur.Web.Entry\\Program.cs"',"{19}":!0,title:'"Fur.Web.Entry\\Program.cs"'}),"using Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Hosting;\n\nnamespace Fur.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")),Object(i.b)("h3",{id:"311-startup-\u4e24\u4e2a\u91cd\u8981\u65b9\u6cd5"},"3.1.1 ",Object(i.b)("inlineCode",{parentName:"h3"},"Startup")," \u4e24\u4e2a\u91cd\u8981\u65b9\u6cd5"),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"Startup")," \u9ed8\u8ba4\u6709\u4e24\u4e2a\u91cd\u8981\u7684\u65b9\u6cd5:"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("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"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"Configure"),"\uff1a\u914d\u7f6e\u5e94\u7528\u8bf7\u6c42\u5904\u7406\u7ba1\u9053")),Object(i.b)("p",null,"\u9ed8\u8ba4\u4ee3\u7801\u5982\u4e0b\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{9,13} title="Fur.Web.Entry\\Startup.cs"',"{9,13}":!0,title:'"Fur.Web.Entry\\Startup.cs"'}),"using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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")),Object(i.b)("p",null,"\u5728\u8fd9\u91cc\uff0c\u4e0d\u6253\u7b97\u8be6\u7ec6\u8bb2 ",Object(i.b)("inlineCode",{parentName:"p"},"Startup")," \u7c7b\u7684\u5177\u4f53\u529f\u80fd\u548c\u4f5c\u7528\u3002"),Object(i.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e86\u89e3\u66f4\u591a")),Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},"\u60f3\u4e86\u89e3\u66f4\u591a ",Object(i.b)("inlineCode",{parentName:"p"},"Startup")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",Object(i.b)("a",Object(a.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"))),Object(i.b)("h2",{id:"32-appstartup"},"3.2 ",Object(i.b)("inlineCode",{parentName:"h2"},"AppStartup")),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u4e2d\uff0c\u63d0\u4f9b\u4e86\u66f4\u4e3a\u7075\u6d3b\u7684 ",Object(i.b)("inlineCode",{parentName:"p"},"Startup")," \u7c7b\u914d\u7f6e\u65b9\u5f0f\uff0c\u65e0\u9700\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Web \u542f\u7528\u5c42")," \u4e2d\u914d\u7f6e\uff0c\u53ef\u5c06\u914d\u7f6e\u653e\u5230\u4efb\u4f55\u9879\u76ee\u5c42\u3002"),Object(i.b)("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"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"Startup")," \u7c7b\u9ed8\u8ba4\u548c ",Object(i.b)("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 ",Object(i.b)("inlineCode",{parentName:"li"},"Web \u5e94\u7528\u5c42"),"\uff0c",Object(i.b)("inlineCode",{parentName:"li"},"Startup")," \u53c8\u8981\u91cd\u65b0\u914d\u7f6e"),Object(i.b)("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 ",Object(i.b)("inlineCode",{parentName:"li"},"Startup")," \u7c7b\u5c31\u4f1a\u53d8\u5f97\u8d8a\u6765\u8d8a\u81c3\u80bf\uff0c\u96be\u4ee5\u7ef4\u62a4"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"Startup")," \u7c7b\u65e0\u6cd5\u5176\u4ed6\u9879\u76ee\u7c7b\u578b\u8fdb\u884c\u5171\u7528")),Object(i.b)("p",null,"\u6240\u4ee5\uff0c",Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u63d0\u4f9b\u4e86\u66f4\u52a0\u7075\u6d3b\u7684\u914d\u7f6e\u65b9\u5f0f\uff1a",Object(i.b)("inlineCode",{parentName:"p"},"AppStartup"),"\u3002"),Object(i.b)("h3",{id:"321-\u5982\u4f55\u914d\u7f6e-appstartup"},"3.2.1 \u5982\u4f55\u914d\u7f6e ",Object(i.b)("inlineCode",{parentName:"h3"},"AppStartup")),Object(i.b)("p",null,Object(i.b)("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"),Object(i.b)("h3",{id:"322-appstartup-\u7ea6\u5b9a"},"3.2.2 ",Object(i.b)("inlineCode",{parentName:"h3"},"AppStartup")," \u7ea6\u5b9a"),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"AppStartup")," \u6d3e\u751f\u7c7b\u53ea\u6709\u4e24\u4e2a\u5c0f\u7ea6\u5b9a\uff1a"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"\u4efb\u4f55\u516c\u5f00\u3001\u975e\u9759\u6001\u3001\u8fd4\u56de\u503c\u4e3a ",Object(i.b)("inlineCode",{parentName:"li"},"void")," \u4e14\u65b9\u6cd5\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f ",Object(i.b)("inlineCode",{parentName:"li"},"IServiceCollection")," \u7c7b\u578b\uff0c\u90a3\u4e48\u4ed6\u5c31\u662f\u4e00\u4e2a ",Object(i.b)("inlineCode",{parentName:"li"},"ConfigureServices")," \u65b9\u6cd5"),Object(i.b)("li",{parentName:"ul"},"\u4efb\u4f55\u516c\u5f00\u3001\u975e\u9759\u6001\u3001\u8fd4\u56de\u503c\u4e3a ",Object(i.b)("inlineCode",{parentName:"li"},"void")," \u4e14\u65b9\u6cd5\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f ",Object(i.b)("inlineCode",{parentName:"li"},"IApplicationBuilder")," \u7c7b\u578b\uff0c\u7b2c\u4e8c\u4e2a\u53c2\u6570\u662f ",Object(i.b)("inlineCode",{parentName:"li"},"IWebHostEnvironment")," \u7c7b\u578b\uff0c\u90a3\u4e48\u4ed6\u5c31\u662f\u4e00\u4e2a ",Object(i.b)("inlineCode",{parentName:"li"},"Configure")," \u65b9\u6cd5")),Object(i.b)("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"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{5,7,12,18,23}","{5,7,12,18,23}":!0}),"using Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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")),Object(i.b)("h3",{id:"323-appstartup-\u914d\u7f6e\u987a\u5e8f"},"3.2.3 ",Object(i.b)("inlineCode",{parentName:"h3"},"AppStartup")," \u914d\u7f6e\u987a\u5e8f"),Object(i.b)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",Object(i.b)("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 ",Object(i.b)("inlineCode",{parentName:"p"},"AppStartup")," \u6d3e\u751f\u7c7b\u4e2d\u8d34 ",Object(i.b)("inlineCode",{parentName:"p"},"[AppStartup(order)]")," \u7279\u6027\u5373\u53ef\u3002"),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"order")," \u6570\u503c\u8d8a\u5927\uff0c\u7ea6\u5728\u524d\u9762\u8c03\u7528\uff0c\u5982\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{5}","{5}":!0}),"using Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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")),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{5}","{5}":!0}),"using Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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")),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"FirstStartup")," \u4f1a\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"SecondStartup")," \u4e4b\u524d\u8c03\u7528\u3002"),Object(i.b)("h3",{id:"324-appstartup-\u65b9\u6cd5\u8c03\u7528\u987a\u5e8f"},"3.2.4 ",Object(i.b)("inlineCode",{parentName:"h3"},"AppStartup")," \u65b9\u6cd5\u8c03\u7528\u987a\u5e8f"),Object(i.b)("p",null,Object(i.b)("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"),Object(i.b)("h2",{id:"33-\u6846\u67b6\u9ed8\u8ba4-appstartup-\u5b9e\u73b0"},"3.3 \u6846\u67b6\u9ed8\u8ba4 ",Object(i.b)("inlineCode",{parentName:"h2"},"AppStartup")," \u5b9e\u73b0"),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u9ed8\u8ba4\u5728\u6bcf\u4e00\u4e2a\u9879\u76ee\u5c42\u4e2d\u90fd\u521b\u5efa\u4e86\u4e00\u4e2a ",Object(i.b)("inlineCode",{parentName:"p"},"AppStartup")," \u6d3e\u751f\u7c7b\uff0c\u65b9\u4fbf\u5927\u5bb6\u914d\u7f6e\u3002\u5982\uff1a"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"FurStartup.cs"),"\uff1a",Object(i.b)("inlineCode",{parentName:"li"},"Fur")," \u6846\u67b6\u6838\u5fc3\u542f\u52a8\u7c7b\uff08\u901a\u5e38\u65e0\u9700\u914d\u7f6e\uff09"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"FurApplicationStartup.cs"),"\uff1a\u4e1a\u52a1\u670d\u52a1\u542f\u52a8\u7c7b"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"FurCoreStartup.cs"),"\uff1a\u5e94\u7528\u6838\u5fc3\u529f\u80fd\u542f\u52a8\u7c7b"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"FurEntityFrameworkCoreStartup.cs"),"\uff1a\u6570\u636e\u5e93\u76f8\u5173\u542f\u52a8\u7c7b"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"FurWebCoreStartup.cs"),"\uff1a",Object(i.b)("inlineCode",{parentName:"li"},"Web")," \u6838\u5fc3\u542f\u52a8\u914d\u7f6e\u7c7b")),Object(i.b)("h2",{id:"34-startup-\u914d\u7f6e\u6700\u4f73\u5b9e\u8df5"},"3.4 ",Object(i.b)("inlineCode",{parentName:"h2"},"Startup")," \u914d\u7f6e\u6700\u4f73\u5b9e\u8df5"),Object(i.b)("p",null,"\u5efa\u8bae ",Object(i.b)("inlineCode",{parentName:"p"},"Web")," \u542f\u52a8\u5c42\u7684 ",Object(i.b)("inlineCode",{parentName:"p"},"Startup.cs")," \u4fdd\u6301\u4e3a\u7a7a\u65b9\u6cd5\u4f53\uff0c\u5982\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'title="Fur.Web.Entry\\Startup.cs"',title:'"Fur.Web.Entry\\Startup.cs"'}),"using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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")),Object(i.b)("p",null,"\u5c06\u6240\u6709 ",Object(i.b)("inlineCode",{parentName:"p"},"Web \u5e94\u7528\u5c42")," \u914d\u7f6e\u8fc1\u79fb\u5230 ",Object(i.b)("inlineCode",{parentName:"p"},"FurWebCoreStartup.cs")," \u4e2d\uff0c\u5982\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'title="Fur.Web.Core\\FurWebCoreStartup.cs"',title:'"Fur.Web.Core\\FurWebCoreStartup.cs"'}),"using Fur.UnifyResult;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace Fur.Web.Core\n{\n [AppStartup(800)]\n public sealed class FurWebCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddCorsAccessor();\n\n services.AddSpecificationDocuments();\n services.AddControllers()\n .AddDynamicApiControllers()\n .AddDataValidation()\n .AddFriendlyException()\n .AddUnifyResult();\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.UseSpecificationDocuments();\n\n app.UseEndpoints(endpoints =>\n {\n endpoints.MapControllers();\n });\n }\n }\n}\n")),Object(i.b)("p",null,"\u8fd9\u6837\uff0c\u540e\u7eed\u66f4\u6362 ",Object(i.b)("inlineCode",{parentName:"p"},"Web \u5e94\u7528\u5c42")," \u4e5f\u65e0\u9700\u91cd\u65b0\u914d\u7f6e ",Object(i.b)("inlineCode",{parentName:"p"},"Startup.cs")),Object(i.b)("h2",{id:"35-\u5173\u4e8e-appsettingsjson"},"3.5 \u5173\u4e8e ",Object(i.b)("inlineCode",{parentName:"h2"},"appsettings.json")),Object(i.b)("p",null,"\u5728\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",Object(i.b)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u914d\u7f6e\u653e\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"appsettings.json")," \u4e2d\u914d\u7f6e\uff0c\u4f46\u662f\u8fd9\u6837\u7684\u65b9\u5f0f\u548c ",Object(i.b)("inlineCode",{parentName:"p"},"Startup.cs")," \u914d\u7f6e\u4e00\u6837\u7684\u9053\u7406\uff0c\u4e00\u65e6\u6211\u4eec\u66f4\u6362\u4e86 ",Object(i.b)("inlineCode",{parentName:"p"},"Web \u5e94\u7528\u5c42"),"\uff0c\u90a3\u4e48 ",Object(i.b)("inlineCode",{parentName:"p"},"appsettings.json")," \u53c8\u8981\u91cd\u65b0\u914d\u7f6e\u4e00\u6b21\u3002"),Object(i.b)("p",null,"\u6240\u4ee5\uff0c",Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u63d0\u4f9b\u4e86\u66f4\u52a0\u7075\u6d3b\u7684\u65b9\u5f0f\u914d\u7f6e ",Object(i.b)("inlineCode",{parentName:"p"},"appsettings.json"),"\uff0c",Object(i.b)("strong",{parentName:"p"},"\u53ea\u9700\u8981\u5728\u4efb\u4f55\u9879\u76ee\u5c42\u6839\u76ee\u5f55\u4e0b\u521b\u5efa ",Object(i.b)("inlineCode",{parentName:"strong"},".json")," \u6587\u4ef6\u5373\u53ef")),Object(i.b)("p",null,Object(i.b)("strong",{parentName:"p"},Object(i.b)("inlineCode",{parentName:"strong"},"Fur")," \u6846\u67b6\u6700\u540e\u4f1a\u81ea\u52a8\u5408\u5e76\u6240\u6709\u5206\u6563\u7684\u914d\u7f6e\u6587\u4ef6\u3002")),Object(i.b)("p",null,"\u5982\u6211\u4eec\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u5c42\u521b\u5efa ",Object(i.b)("inlineCode",{parentName:"p"},"dbsettings.json")," \u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u5982\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-json",metastring:'title="Fur.EntityFramework.Core\\dbsettings.json"',title:'"Fur.EntityFramework.Core\\dbsettings.json"'}),'{\n "ConnectionStrings": {\n "DbConnectionString": "Server=localhost;Database=Fur;User=sa;Password=000000;MultipleActiveResultSets=True;",\n "Sqlite3ConnectionString": "Data Source=./Fur.db"\n }\n}\n')),Object(i.b)("p",null,Object(i.b)("strong",{parentName:"p"},"\u65e0\u9700\u5728 ",Object(i.b)("inlineCode",{parentName:"strong"},"appsettings.json")," \u4e2d\u914d\u7f6e"),"\uff0c\u4e0b\u9762\u662f ",Object(i.b)("inlineCode",{parentName:"p"},"appsettings.json")," \u9ed8\u8ba4\u4ee3\u7801:"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-json"}),'{\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')),Object(i.b)("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"),Object(i.b)("h2",{id:"36-\u795e\u5947\u7684-inject"},"3.6 \u795e\u5947\u7684 ",Object(i.b)("inlineCode",{parentName:"h2"},"Inject()")),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"Inject()")," \u65b9\u6cd5\u662f ",Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u63d0\u4f9b\u7684\u6700\u5c0f\u4fb5\u5165\u5f0f\u7684\u65b9\u6cd5\uff0c\u53ef\u4ee5\u8ba9\u4efb\u4f55 ",Object(i.b)("inlineCode",{parentName:"p"},"ASP.NET Core")," Web\u9879\u76ee\u77ac\u95f4\u652f\u6301\u6240\u6709 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u7279\u6027\u3002"),Object(i.b)("p",null,"\u6211\u4eec\u521b\u5efa\u4e86\u65b0\u7684 ",Object(i.b)("inlineCode",{parentName:"p"},"Web \u9879\u76ee"),"\uff0c\u53ea\u9700\u8981\u4e24\u4e2a\u6b65\u9aa4\u5373\u53ef\uff1a"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"\u6dfb\u52a0 ",Object(i.b)("inlineCode",{parentName:"li"},"Fur.Web.Core")," \u9879\u76ee\u5f15\u7528"),Object(i.b)("li",{parentName:"ul"},"\u5728 ",Object(i.b)("inlineCode",{parentName:"li"},"Program.cs")," \u4e2d\u8c03\u7528\u5373\u53ef")),Object(i.b)("p",null,"\u5982\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{18}","{18}":!0}),"using Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Hosting;\n\nnamespace Fur.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")),Object(i.b)("p",null,"\u975e\u5e38\u7b80\u5355\u5427\u3002\u6211\u4eec\u540e\u7eed\u521b\u5efa\u4efb\u4f55 ",Object(i.b)("inlineCode",{parentName:"p"},"MVC"),"\uff0c",Object(i.b)("inlineCode",{parentName:"p"},"RazorPages"),"\uff0c",Object(i.b)("inlineCode",{parentName:"p"},"Blazor")," \u9879\u76ee\u53ea\u9700\u8981\u6dfb\u52a0 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Web.Core")," \u5f15\u7528\u548c\u8c03\u7528 ",Object(i.b)("inlineCode",{parentName:"p"},"Inject()")," \u5373\u53ef\u3002"),Object(i.b)("h2",{id:"37-\u53cd\u9988\u4e0e\u5efa\u8bae"},"3.7 \u53cd\u9988\u4e0e\u5efa\u8bae"),Object(i.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e0e\u6211\u4eec\u4ea4\u6d41")),Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},"\u7ed9 Fur \u63d0 ",Object(i.b)("a",Object(a.a)({parentName:"p"},{href:"https://gitee.com/monksoul/Fur/issues/new?issue"}),"Issue"),"\u3002"))))}l.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/5ce0ebbd.39ab69aa.js b/docs/5ce0ebbd.39ab69aa.js deleted file mode 100644 index 025354a4a4b..00000000000 --- a/docs/5ce0ebbd.39ab69aa.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[33],{138:function(e,t,r){"use strict";r.d(t,"a",(function(){return s})),r.d(t,"b",(function(){return m}));var n=r(0),o=r.n(n);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 c(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 u=o.a.createContext({}),l=function(e){var t=o.a.useContext(u),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},s=function(e){var t=l(e.components);return o.a.createElement(u.Provider,{value:t},e.children)},f={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},d=o.a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,a=e.originalType,c=e.parentName,u=p(e,["components","mdxType","originalType","parentName"]),s=l(r),d=n,m=s["".concat(c,".").concat(d)]||s[d]||f[d]||a;return r?o.a.createElement(m,i(i({ref:t},u),{},{components:r})):o.a.createElement(m,i({ref:t},u))}));function m(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=r.length,c=new Array(a);c[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:n,c[1]=i;for(var u=2;u=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var s=o.a.createContext({}),d=function(e){var n=o.a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},u=function(e){var n=d(e.components);return o.a.createElement(s.Provider,{value:n},e.children)},b={inlineCode:"code",wrapper:function(e){var n=e.children;return o.a.createElement(o.a.Fragment,{},n)}},m=o.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,c=e.originalType,r=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),u=d(t),m=a,p=u["".concat(r,".").concat(m)]||u[m]||b[m]||c;return t?o.a.createElement(p,i(i({ref:n},s),{},{components:t})):o.a.createElement(p,i({ref:n},s))}));function p(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var c=t.length,r=new Array(c);r[0]=m;var i={};for(var l in n)hasOwnProperty.call(n,l)&&(i[l]=n[l]);i.originalType=e,i.mdxType="string"==typeof e?e:a,r[1]=i;for(var s=2;sDbConnectionInterceptor",id:"92421-dbconnectioninterceptor",children:[]},{value:"9.24.2.2 DbCommandInterceptor",id:"92422-dbcommandinterceptor",children:[]},{value:"9.24.2.3 SaveChangesInterceptor",id:"92423-savechangesinterceptor",children:[]}]},{value:"9.24.3 \u6ce8\u518c\u81ea\u5b9a\u4e49\u8fc7\u6ee4\u5668",id:"9243-\u6ce8\u518c\u81ea\u5b9a\u4e49\u8fc7\u6ee4\u5668",children:[]},{value:"9.24.4 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9244-\u53cd\u9988\u4e0e\u5efa\u8bae",children:[]}],s={rightToc:l};function d(e){var n=e.components,t=Object(o.a)(e,["components"]);return Object(c.b)("wrapper",Object(a.a)({},s,t,{components:n,mdxType:"MDXLayout"}),Object(c.b)("h2",{id:"9241-\u6570\u636e\u5e93\u62e6\u622a\u5668"},"9.24.1 \u6570\u636e\u5e93\u62e6\u622a\u5668"),Object(c.b)("p",null,Object(c.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u63d0\u4f9b\u4e09\u79cd\u6570\u636e\u5e93\u64cd\u4f5c\u62e6\u622a\u5668\uff0c\u53ef\u4ee5\u901a\u8fc7\u62e6\u622a\u5668\u52a8\u6001\u4fee\u6539\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u52a8\u6001\u4fee\u6539sql\uff0c\u52a8\u6001\u66f4\u6539\u53c2\u6570\u7b49\u64cd\u4f5c\u3002"),Object(c.b)("p",null,"\u76ee\u524d\u652f\u6301\u8fd9\u4e09\u79cd\u62e6\u622a\u5668\uff1a"),Object(c.b)("ul",null,Object(c.b)("li",{parentName:"ul"},Object(c.b)("inlineCode",{parentName:"li"},"DbConnectionInterceptor"),"\uff1a\u6570\u636e\u5e93\u8fde\u63a5\u62e6\u622a\u5668"),Object(c.b)("li",{parentName:"ul"},Object(c.b)("inlineCode",{parentName:"li"},"DbCommandInterceptor"),"\uff1a\u6570\u636e\u5e93\u6267\u884c ",Object(c.b)("inlineCode",{parentName:"li"},"Sql")," \u62e6\u622a\u5668"),Object(c.b)("li",{parentName:"ul"},Object(c.b)("inlineCode",{parentName:"li"},"SaveChangesInterceptor"),"\uff1a\u63d0\u4ea4\u5230\u6570\u636e\u5e93\u62e6\u622a\u5668")),Object(c.b)("h2",{id:"9242-\u652f\u6301\u62e6\u622a\u7c7b\u578b"},"9.24.2 \u652f\u6301\u62e6\u622a\u7c7b\u578b"),Object(c.b)("h3",{id:"92421-dbconnectioninterceptor"},"9.24.2.1 ",Object(c.b)("inlineCode",{parentName:"h3"},"DbConnectionInterceptor")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"using Microsoft.EntityFrameworkCore.Diagnostics;\nusing System.Data.Common;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Fur.DatabaseAccessor.Interceptors\n{\n public class SqlConnectionInterceptor : DbConnectionInterceptor\n {\n // \u6570\u636e\u5e93\u8fde\u63a5\u4e4b\u524d\n public override InterceptionResult ConnectionOpening(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)\n {\n return base.ConnectionOpening(connection, eventData, result);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask ConnectionOpeningAsync(DbConnection connection, ConnectionEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n return base.ConnectionOpeningAsync(connection, eventData, result, cancellationToken);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u6210\u529f\n public override void ConnectionOpened(DbConnection connection, ConnectionEndEventData eventData)\n {\n base.ConnectionOpened(connection, eventData);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u6210\u529f\uff08\u5f02\u6b65\uff09\n public override Task ConnectionOpenedAsync(DbConnection connection, ConnectionEndEventData eventData, CancellationToken cancellationToken = default)\n {\n return base.ConnectionOpenedAsync(connection, eventData, cancellationToken);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5173\u95ed\u4e4b\u524d\n public override InterceptionResult ConnectionClosing(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)\n {\n return base.ConnectionClosing(connection, eventData, result);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5173\u95ed\u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask ConnectionClosingAsync(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)\n {\n return base.ConnectionClosingAsync(connection, eventData, result);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5173\u95ed\u6210\u529f\n public override void ConnectionClosed(DbConnection connection, ConnectionEndEventData eventData)\n {\n base.ConnectionClosed(connection, eventData);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5173\u95ed\u6210\u529f\uff08\u5f02\u6b65\uff09\n public override Task ConnectionClosedAsync(DbConnection connection, ConnectionEndEventData eventData)\n {\n return base.ConnectionClosedAsync(connection, eventData);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5931\u8d25\n public override void ConnectionFailed(DbConnection connection, ConnectionErrorEventData eventData)\n {\n base.ConnectionFailed(connection, eventData);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5931\u8d25\uff08\u5f02\u6b65\uff09\n public override Task ConnectionFailedAsync(DbConnection connection, ConnectionErrorEventData eventData, CancellationToken cancellationToken = default)\n {\n return base.ConnectionFailedAsync(connection, eventData, cancellationToken);\n }\n }\n}\n")),Object(c.b)("h3",{id:"92422-dbcommandinterceptor"},"9.24.2.2 ",Object(c.b)("inlineCode",{parentName:"h3"},"DbCommandInterceptor")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"using Microsoft.EntityFrameworkCore.Diagnostics;\nusing System.Data.Common;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Fur.DatabaseAccessor\n{\n internal sealed class SqlCommandProfilerInterceptor : DbCommandInterceptor\n {\n // \u521b\u5efa\u547d\u4ee4\u5bf9\u8c61\u4e4b\u524d\n public override InterceptionResult CommandCreating(CommandCorrelatedEventData eventData, InterceptionResult result)\n {\n return base.CommandCreating(eventData, result);\n }\n\n // \u521b\u5efa\u547d\u4ee4\u5bf9\u8c61\u4e4b\u540e\n public override DbCommand CommandCreated(CommandEndEventData eventData, DbCommand result)\n {\n return base.CommandCreated(eventData, result);\n }\n\n // \u521b\u5efa\u547d\u4ee4\u5bf9\u8c61\u5931\u8d25\n public override void CommandFailed(DbCommand command, CommandErrorEventData eventData)\n {\n base.CommandFailed(command, eventData);\n }\n\n // \u521b\u5efa\u547d\u4ee4\u5bf9\u8c61\u5931\u8d25\uff08\u5f02\u6b65\uff09\n public override Task CommandFailedAsync(DbCommand command, CommandErrorEventData eventData, CancellationToken cancellationToken = default)\n {\n return base.CommandFailedAsync(command, eventData, cancellationToken);\n }\n\n // \u8bfb\u53d6\u6570\u636e\u4e4b\u524d\n public override InterceptionResult ReaderExecuting(DbCommand command, CommandEventData eventData, InterceptionResult result)\n {\n return base.ReaderExecuting(command, eventData, result);\n }\n\n // \u8bfb\u53d6\u6570\u636e\u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask> ReaderExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n return base.ReaderExecutingAsync(command, eventData, result, cancellationToken);\n }\n\n // \u8bfb\u53d6\u6570\u636e\u4e4b\u540e\n public override DbDataReader ReaderExecuted(DbCommand command, CommandExecutedEventData eventData, DbDataReader result)\n {\n return base.ReaderExecuted(command, eventData, result);\n }\n\n // \u8bfb\u53d6\u6570\u636e\u4e4b\u540e\uff08\u5f02\u6b65\uff09\n public override ValueTask ReaderExecutedAsync(DbCommand command, CommandExecutedEventData eventData, DbDataReader result, CancellationToken cancellationToken = default)\n {\n return base.ReaderExecutedAsync(command, eventData, result, cancellationToken);\n }\n\n // DataReader \u5bf9\u8c61\u91ca\u653e\u4e4b\u524d\n public override InterceptionResult DataReaderDisposing(DbCommand command, DataReaderDisposingEventData eventData, InterceptionResult result)\n {\n return base.DataReaderDisposing(command, eventData, result);\n }\n\n // \u65e0\u67e5\u8be2\u6267\u884c sql \u4e4b\u524d\n public override InterceptionResult NonQueryExecuting(DbCommand command, CommandEventData eventData, InterceptionResult result)\n {\n return base.NonQueryExecuting(command, eventData, result);\n }\n\n // \u65e0\u67e5\u8be2\u6267\u884c sql \u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask> NonQueryExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n return base.NonQueryExecutingAsync(command, eventData, result, cancellationToken);\n }\n\n // \u65e0\u67e5\u8be2\u6267\u884c sql \u4e4b\u540e\n public override int NonQueryExecuted(DbCommand command, CommandExecutedEventData eventData, int result)\n {\n return base.NonQueryExecuted(command, eventData, result);\n }\n\n // \u65e0\u67e5\u8be2\u6267\u884c sql \u4e4b\u540e\uff08\u5f02\u6b65\uff09\n public override ValueTask NonQueryExecutedAsync(DbCommand command, CommandExecutedEventData eventData, int result, CancellationToken cancellationToken = default)\n {\n return base.NonQueryExecutedAsync(command, eventData, result, cancellationToken);\n }\n\n // \u6267\u884c sql \u8fd4\u56de\u5355\u884c\u5355\u5217\u4e4b\u524d\n public override InterceptionResult ScalarExecuting(DbCommand command, CommandEventData eventData, InterceptionResult result)\n {\n return base.ScalarExecuting(command, eventData, result);\n }\n\n // \u6267\u884c sql \u8fd4\u56de\u5355\u884c\u5355\u5217\u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask> ScalarExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n return base.ScalarExecutingAsync(command, eventData, result, cancellationToken);\n }\n\n // \u6267\u884c sql \u8fd4\u56de\u5355\u884c\u5355\u5217\u4e4b\u540e\n public override object ScalarExecuted(DbCommand command, CommandExecutedEventData eventData, object result)\n {\n return base.ScalarExecuted(command, eventData, result);\n }\n\n // \u6267\u884c sql \u8fd4\u56de\u5355\u884c\u5355\u5217\u4e4b\u540e\uff08\u5f02\u6b65\uff09\n public override ValueTask ScalarExecutedAsync(DbCommand command, CommandExecutedEventData eventData, object result, CancellationToken cancellationToken = default)\n {\n return base.ScalarExecutedAsync(command, eventData, result, cancellationToken);\n }\n }\n}\n")),Object(c.b)("h3",{id:"92423-savechangesinterceptor"},"9.24.2.3 ",Object(c.b)("inlineCode",{parentName:"h3"},"SaveChangesInterceptor")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"using Microsoft.EntityFrameworkCore.Diagnostics;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Fur.DatabaseAccessor\n{\n public class DbContextSaveChangesInterceptor : SaveChangesInterceptor\n {\n // \u63d0\u4ea4\u5230\u6570\u636e\u5e93\u4e4b\u524d\n public override InterceptionResult SavingChanges(DbContextEventData eventData, InterceptionResult result)\n {\n return base.SavingChanges(eventData, result);\n }\n\n // \u63d0\u4ea4\u5230\u6570\u636e\u5e93\u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask> SavingChangesAsync(DbContextEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n return base.SavingChangesAsync(eventData, result, cancellationToken);\n }\n\n // \u63d0\u4ea4\u5230\u6570\u636e\u5e93\u4e4b\u540e\n public override int SavedChanges(SaveChangesCompletedEventData eventData, int result)\n {\n return base.SavedChanges(eventData, result);\n }\n\n // \u63d0\u4ea4\u5230\u6570\u636e\u5e93\u4e4b\u540e\uff08\u5f02\u6b65\uff09\n public override ValueTask SavedChangesAsync(SaveChangesCompletedEventData eventData, int result, CancellationToken cancellationToken = default)\n {\n return base.SavedChangesAsync(eventData, result, cancellationToken);\n }\n\n // \u63d0\u4ea4\u6570\u636e\u5e93\u5931\u8d25\n public override void SaveChangesFailed(DbContextErrorEventData eventData)\n {\n base.SaveChangesFailed(eventData);\n }\n\n // \u63d0\u4ea4\u6570\u636e\u5e93\u5931\u8d25\uff08\u5f02\u6b65\uff09\n public override Task SaveChangesFailedAsync(DbContextErrorEventData eventData, CancellationToken cancellationToken = default)\n {\n return base.SaveChangesFailedAsync(eventData, cancellationToken);\n }\n }\n}\n")),Object(c.b)("h2",{id:"9243-\u6ce8\u518c\u81ea\u5b9a\u4e49\u8fc7\u6ee4\u5668"},"9.24.3 \u6ce8\u518c\u81ea\u5b9a\u4e49\u8fc7\u6ee4\u5668"),Object(c.b)("p",null,"\u5b9a\u4e49\u597d\u8fc7\u6ee4\u5668\u4e4b\u540e\uff0c\u6211\u4eec\u9700\u8981\u5728\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u6ce8\u518c\uff1a"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"services.AddSqlitePool(interceptors: new IInterceptor[] {\n new SqlConnectionProfilerInterceptor(),\n new DbContextSaveChangesInterceptor(),\n new SqlCommandProfilerInterceptor()\n});\n")),Object(c.b)("h2",{id:"9244-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.24.4 \u53cd\u9988\u4e0e\u5efa\u8bae"),Object(c.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(c.b)("h5",{parentName:"div"},Object(c.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(c.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(c.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e0e\u6211\u4eec\u4ea4\u6d41")),Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(c.b)("p",{parentName:"div"},"\u7ed9 Fur \u63d0 ",Object(c.b)("a",Object(a.a)({parentName:"p"},{href:"https://gitee.com/monksoul/Fur/issues/new?issue"}),"Issue"),"\u3002"))))}d.isMDXComponent=!0}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[39],{138:function(e,n,t){"use strict";t.d(n,"a",(function(){return u})),t.d(n,"b",(function(){return p}));var a=t(0),o=t.n(a);function c(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 i(e){for(var n=1;n=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var s=o.a.createContext({}),d=function(e){var n=o.a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},u=function(e){var n=d(e.components);return o.a.createElement(s.Provider,{value:n},e.children)},b={inlineCode:"code",wrapper:function(e){var n=e.children;return o.a.createElement(o.a.Fragment,{},n)}},m=o.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,c=e.originalType,r=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),u=d(t),m=a,p=u["".concat(r,".").concat(m)]||u[m]||b[m]||c;return t?o.a.createElement(p,i(i({ref:n},s),{},{components:t})):o.a.createElement(p,i({ref:n},s))}));function p(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var c=t.length,r=new Array(c);r[0]=m;var i={};for(var l in n)hasOwnProperty.call(n,l)&&(i[l]=n[l]);i.originalType=e,i.mdxType="string"==typeof e?e:a,r[1]=i;for(var s=2;sDbConnectionInterceptor",id:"92421-dbconnectioninterceptor",children:[]},{value:"9.24.2.2 DbCommandInterceptor",id:"92422-dbcommandinterceptor",children:[]},{value:"9.24.2.3 SaveChangesInterceptor",id:"92423-savechangesinterceptor",children:[]}]},{value:"9.24.3 \u6ce8\u518c\u81ea\u5b9a\u4e49\u8fc7\u6ee4\u5668",id:"9243-\u6ce8\u518c\u81ea\u5b9a\u4e49\u8fc7\u6ee4\u5668",children:[]},{value:"9.24.4 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9244-\u53cd\u9988\u4e0e\u5efa\u8bae",children:[]}],s={rightToc:l};function d(e){var n=e.components,t=Object(o.a)(e,["components"]);return Object(c.b)("wrapper",Object(a.a)({},s,t,{components:n,mdxType:"MDXLayout"}),Object(c.b)("h2",{id:"9241-\u6570\u636e\u5e93\u62e6\u622a\u5668"},"9.24.1 \u6570\u636e\u5e93\u62e6\u622a\u5668"),Object(c.b)("p",null,Object(c.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u63d0\u4f9b\u4e09\u79cd\u6570\u636e\u5e93\u64cd\u4f5c\u62e6\u622a\u5668\uff0c\u53ef\u4ee5\u901a\u8fc7\u62e6\u622a\u5668\u52a8\u6001\u4fee\u8be5\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u52a8\u6001\u4fee\u6539sql\uff0c\u52a8\u6001\u66f4\u6539\u53c2\u6570\u7b49\u64cd\u4f5c\u3002"),Object(c.b)("p",null,"\u76ee\u524d\u652f\u6301\u8fd9\u4e09\u79cd\u62e6\u622a\u5668\uff1a"),Object(c.b)("ul",null,Object(c.b)("li",{parentName:"ul"},Object(c.b)("inlineCode",{parentName:"li"},"DbConnectionInterceptor"),"\uff1a\u6570\u636e\u5e93\u8fde\u63a5\u62e6\u622a\u5668"),Object(c.b)("li",{parentName:"ul"},Object(c.b)("inlineCode",{parentName:"li"},"DbCommandInterceptor"),"\uff1a\u6570\u636e\u5e93\u6267\u884c ",Object(c.b)("inlineCode",{parentName:"li"},"Sql")," \u62e6\u622a\u5668"),Object(c.b)("li",{parentName:"ul"},Object(c.b)("inlineCode",{parentName:"li"},"SaveChangesInterceptor"),"\uff1a\u63d0\u4ea4\u5230\u6570\u636e\u5e93\u62e6\u622a\u5668")),Object(c.b)("h2",{id:"9242-\u652f\u6301\u62e6\u622a\u7c7b\u578b"},"9.24.2 \u652f\u6301\u62e6\u622a\u7c7b\u578b"),Object(c.b)("h3",{id:"92421-dbconnectioninterceptor"},"9.24.2.1 ",Object(c.b)("inlineCode",{parentName:"h3"},"DbConnectionInterceptor")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"using Microsoft.EntityFrameworkCore.Diagnostics;\nusing System.Data.Common;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Fur.DatabaseAccessor.Interceptors\n{\n public class SqlConnectionInterceptor : DbConnectionInterceptor\n {\n // \u6570\u636e\u5e93\u8fde\u63a5\u4e4b\u524d\n public override InterceptionResult ConnectionOpening(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)\n {\n return base.ConnectionOpening(connection, eventData, result);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask ConnectionOpeningAsync(DbConnection connection, ConnectionEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n return base.ConnectionOpeningAsync(connection, eventData, result, cancellationToken);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u6210\u529f\n public override void ConnectionOpened(DbConnection connection, ConnectionEndEventData eventData)\n {\n base.ConnectionOpened(connection, eventData);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u6210\u529f\uff08\u5f02\u6b65\uff09\n public override Task ConnectionOpenedAsync(DbConnection connection, ConnectionEndEventData eventData, CancellationToken cancellationToken = default)\n {\n return base.ConnectionOpenedAsync(connection, eventData, cancellationToken);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5173\u95ed\u4e4b\u524d\n public override InterceptionResult ConnectionClosing(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)\n {\n return base.ConnectionClosing(connection, eventData, result);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5173\u95ed\u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask ConnectionClosingAsync(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)\n {\n return base.ConnectionClosingAsync(connection, eventData, result);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5173\u95ed\u6210\u529f\n public override void ConnectionClosed(DbConnection connection, ConnectionEndEventData eventData)\n {\n base.ConnectionClosed(connection, eventData);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5173\u95ed\u6210\u529f\uff08\u5f02\u6b65\uff09\n public override Task ConnectionClosedAsync(DbConnection connection, ConnectionEndEventData eventData)\n {\n return base.ConnectionClosedAsync(connection, eventData);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5931\u8d25\n public override void ConnectionFailed(DbConnection connection, ConnectionErrorEventData eventData)\n {\n base.ConnectionFailed(connection, eventData);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5931\u8d25\uff08\u5f02\u6b65\uff09\n public override Task ConnectionFailedAsync(DbConnection connection, ConnectionErrorEventData eventData, CancellationToken cancellationToken = default)\n {\n return base.ConnectionFailedAsync(connection, eventData, cancellationToken);\n }\n }\n}\n")),Object(c.b)("h3",{id:"92422-dbcommandinterceptor"},"9.24.2.2 ",Object(c.b)("inlineCode",{parentName:"h3"},"DbCommandInterceptor")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"using Microsoft.EntityFrameworkCore.Diagnostics;\nusing System.Data.Common;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Fur.DatabaseAccessor\n{\n internal sealed class SqlCommandProfilerInterceptor : DbCommandInterceptor\n {\n // \u521b\u5efa\u547d\u4ee4\u5bf9\u8c61\u4e4b\u524d\n public override InterceptionResult CommandCreating(CommandCorrelatedEventData eventData, InterceptionResult result)\n {\n return base.CommandCreating(eventData, result);\n }\n\n // \u521b\u5efa\u547d\u4ee4\u5bf9\u8c61\u4e4b\u540e\n public override DbCommand CommandCreated(CommandEndEventData eventData, DbCommand result)\n {\n return base.CommandCreated(eventData, result);\n }\n\n // \u521b\u5efa\u547d\u4ee4\u5bf9\u8c61\u5931\u8d25\n public override void CommandFailed(DbCommand command, CommandErrorEventData eventData)\n {\n base.CommandFailed(command, eventData);\n }\n\n // \u521b\u5efa\u547d\u4ee4\u5bf9\u8c61\u5931\u8d25\uff08\u5f02\u6b65\uff09\n public override Task CommandFailedAsync(DbCommand command, CommandErrorEventData eventData, CancellationToken cancellationToken = default)\n {\n return base.CommandFailedAsync(command, eventData, cancellationToken);\n }\n\n // \u8bfb\u53d6\u6570\u636e\u4e4b\u524d\n public override InterceptionResult ReaderExecuting(DbCommand command, CommandEventData eventData, InterceptionResult result)\n {\n return base.ReaderExecuting(command, eventData, result);\n }\n\n // \u8bfb\u53d6\u6570\u636e\u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask> ReaderExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n return base.ReaderExecutingAsync(command, eventData, result, cancellationToken);\n }\n\n // \u8bfb\u53d6\u6570\u636e\u4e4b\u540e\n public override DbDataReader ReaderExecuted(DbCommand command, CommandExecutedEventData eventData, DbDataReader result)\n {\n return base.ReaderExecuted(command, eventData, result);\n }\n\n // \u8bfb\u53d6\u6570\u636e\u4e4b\u540e\uff08\u5f02\u6b65\uff09\n public override ValueTask ReaderExecutedAsync(DbCommand command, CommandExecutedEventData eventData, DbDataReader result, CancellationToken cancellationToken = default)\n {\n return base.ReaderExecutedAsync(command, eventData, result, cancellationToken);\n }\n\n // DataReader \u5bf9\u8c61\u91ca\u653e\u4e4b\u524d\n public override InterceptionResult DataReaderDisposing(DbCommand command, DataReaderDisposingEventData eventData, InterceptionResult result)\n {\n return base.DataReaderDisposing(command, eventData, result);\n }\n\n // \u65e0\u67e5\u8be2\u6267\u884c sql \u4e4b\u524d\n public override InterceptionResult NonQueryExecuting(DbCommand command, CommandEventData eventData, InterceptionResult result)\n {\n return base.NonQueryExecuting(command, eventData, result);\n }\n\n // \u65e0\u67e5\u8be2\u6267\u884c sql \u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask> NonQueryExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n return base.NonQueryExecutingAsync(command, eventData, result, cancellationToken);\n }\n\n // \u65e0\u67e5\u8be2\u6267\u884c sql \u4e4b\u540e\n public override int NonQueryExecuted(DbCommand command, CommandExecutedEventData eventData, int result)\n {\n return base.NonQueryExecuted(command, eventData, result);\n }\n\n // \u65e0\u67e5\u8be2\u6267\u884c sql \u4e4b\u540e\uff08\u5f02\u6b65\uff09\n public override ValueTask NonQueryExecutedAsync(DbCommand command, CommandExecutedEventData eventData, int result, CancellationToken cancellationToken = default)\n {\n return base.NonQueryExecutedAsync(command, eventData, result, cancellationToken);\n }\n\n // \u6267\u884c sql \u8fd4\u56de\u5355\u884c\u5355\u5217\u4e4b\u524d\n public override InterceptionResult ScalarExecuting(DbCommand command, CommandEventData eventData, InterceptionResult result)\n {\n return base.ScalarExecuting(command, eventData, result);\n }\n\n // \u6267\u884c sql \u8fd4\u56de\u5355\u884c\u5355\u5217\u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask> ScalarExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n return base.ScalarExecutingAsync(command, eventData, result, cancellationToken);\n }\n\n // \u6267\u884c sql \u8fd4\u56de\u5355\u884c\u5355\u5217\u4e4b\u540e\n public override object ScalarExecuted(DbCommand command, CommandExecutedEventData eventData, object result)\n {\n return base.ScalarExecuted(command, eventData, result);\n }\n\n // \u6267\u884c sql \u8fd4\u56de\u5355\u884c\u5355\u5217\u4e4b\u540e\uff08\u5f02\u6b65\uff09\n public override ValueTask ScalarExecutedAsync(DbCommand command, CommandExecutedEventData eventData, object result, CancellationToken cancellationToken = default)\n {\n return base.ScalarExecutedAsync(command, eventData, result, cancellationToken);\n }\n }\n}\n")),Object(c.b)("h3",{id:"92423-savechangesinterceptor"},"9.24.2.3 ",Object(c.b)("inlineCode",{parentName:"h3"},"SaveChangesInterceptor")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"using Microsoft.EntityFrameworkCore.Diagnostics;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Fur.DatabaseAccessor\n{\n public class DbContextSaveChangesInterceptor : SaveChangesInterceptor\n {\n // \u63d0\u4ea4\u5230\u6570\u636e\u5e93\u4e4b\u524d\n public override InterceptionResult SavingChanges(DbContextEventData eventData, InterceptionResult result)\n {\n return base.SavingChanges(eventData, result);\n }\n\n // \u63d0\u4ea4\u5230\u6570\u636e\u5e93\u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask> SavingChangesAsync(DbContextEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n return base.SavingChangesAsync(eventData, result, cancellationToken);\n }\n\n // \u63d0\u4ea4\u5230\u6570\u636e\u5e93\u4e4b\u540e\n public override int SavedChanges(SaveChangesCompletedEventData eventData, int result)\n {\n return base.SavedChanges(eventData, result);\n }\n\n // \u63d0\u4ea4\u5230\u6570\u636e\u5e93\u4e4b\u540e\uff08\u5f02\u6b65\uff09\n public override ValueTask SavedChangesAsync(SaveChangesCompletedEventData eventData, int result, CancellationToken cancellationToken = default)\n {\n return base.SavedChangesAsync(eventData, result, cancellationToken);\n }\n\n // \u63d0\u4ea4\u6570\u636e\u5e93\u5931\u8d25\n public override void SaveChangesFailed(DbContextErrorEventData eventData)\n {\n base.SaveChangesFailed(eventData);\n }\n\n // \u63d0\u4ea4\u6570\u636e\u5e93\u5931\u8d25\uff08\u5f02\u6b65\uff09\n public override Task SaveChangesFailedAsync(DbContextErrorEventData eventData, CancellationToken cancellationToken = default)\n {\n return base.SaveChangesFailedAsync(eventData, cancellationToken);\n }\n }\n}\n")),Object(c.b)("h2",{id:"9243-\u6ce8\u518c\u81ea\u5b9a\u4e49\u8fc7\u6ee4\u5668"},"9.24.3 \u6ce8\u518c\u81ea\u5b9a\u4e49\u8fc7\u6ee4\u5668"),Object(c.b)("p",null,"\u5b9a\u4e49\u597d\u8fc7\u6ee4\u5668\u4e4b\u540e\uff0c\u6211\u4eec\u9700\u8981\u5728\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u6ce8\u518c\uff1a"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"services.AddSqlitePool(interceptors: new IInterceptor[] {\n new SqlConnectionProfilerInterceptor(),\n new DbContextSaveChangesInterceptor(),\n new SqlCommandProfilerInterceptor()\n});\n")),Object(c.b)("h2",{id:"9244-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.24.4 \u53cd\u9988\u4e0e\u5efa\u8bae"),Object(c.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(c.b)("h5",{parentName:"div"},Object(c.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(c.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(c.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e0e\u6211\u4eec\u4ea4\u6d41")),Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(c.b)("p",{parentName:"div"},"\u7ed9 Fur \u63d0 ",Object(c.b)("a",Object(a.a)({parentName:"p"},{href:"https://gitee.com/monksoul/Fur/issues/new?issue"}),"Issue"),"\u3002"))))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/blog/index.html b/docs/blog/index.html index e78446ad1b6..58f22142444 100644 --- a/docs/blog/index.html +++ b/docs/blog/index.html @@ -6,7 +6,7 @@ Blog | Fur - + @@ -25,7 +25,7 @@

Fur 介绍

dotnet中国

dotnet中国

为中国 .NET 开发者提供优质的资讯和技术分享。

star fork GitHub stars GitHub forks GitHub license

Fur.NET 5 平台下极易入门、极速开发的 Web 应用框架。

🍕 名字的由来

故事是这样子的:

起初,想开发一个极易入门、极易维护的框架,开发理念为:一切从简,只为了更懒

所以自然而然想到了:Lazier,也就是 更懒 的意思。但是 更懒更烂 读音相近且中文名没有特色,对此换名问题我苦恼了好几天。

刚好有一次我在博客园中帮一个博友解答问题,解决后博友赞扬我对 .NET Core 颇有了解,我就顺嘴回答了一句:“略懂皮毛”

就这时,脑瓜子灵机一动,干脆起名为:“皮毛”?英文单词 Fur [fɜː(r)]”,单词又短而且中文读音既俗气又顺口。😄😎

所以,Fur 就诞生了。

之后就有了 “小僧不才,略懂皮毛(Fur)。” 广告语 和 chinadot.net 域名。

🍔 关于 LOGO

Fur LOGO 设计由 F U R 三个单词组成:

我相信很多人看到 Fur 的 LOGO 时都会问:“为什么选择奶牛?”,因为 那些年吹过的牛逼都实现了 🐮

之所以选择 奶牛 是因为 具有脚踏实地,任劳任怨的做事风格,同时 奶牛 意味着丰富的营养价值,正如 Fur 所能带给你的。

🍟 文档地址

https://chinadot.net

- + diff --git a/docs/blog/tags/fur/index.html b/docs/blog/tags/fur/index.html index b6d08dd9486..1161cb37d4f 100644 --- a/docs/blog/tags/fur/index.html +++ b/docs/blog/tags/fur/index.html @@ -6,7 +6,7 @@ Posts tagged "fur" | Fur - + @@ -25,7 +25,7 @@

1 post tagged with "fur"

View All Tags

Fur 介绍

dotnet中国

dotnet中国

为中国 .NET 开发者提供优质的资讯和技术分享。

star fork GitHub stars GitHub forks GitHub license

Fur.NET 5 平台下极易入门、极速开发的 Web 应用框架。

🍕 名字的由来

故事是这样子的:

起初,想开发一个极易入门、极易维护的框架,开发理念为:一切从简,只为了更懒

所以自然而然想到了:Lazier,也就是 更懒 的意思。但是 更懒更烂 读音相近且中文名没有特色,对此换名问题我苦恼了好几天。

刚好有一次我在博客园中帮一个博友解答问题,解决后博友赞扬我对 .NET Core 颇有了解,我就顺嘴回答了一句:“略懂皮毛”

就这时,脑瓜子灵机一动,干脆起名为:“皮毛”?英文单词 Fur [fɜː(r)]”,单词又短而且中文读音既俗气又顺口。😄😎

所以,Fur 就诞生了。

之后就有了 “小僧不才,略懂皮毛(Fur)。” 广告语 和 chinadot.net 域名。

🍔 关于 LOGO

Fur LOGO 设计由 F U R 三个单词组成:

我相信很多人看到 Fur 的 LOGO 时都会问:“为什么选择奶牛?”,因为 那些年吹过的牛逼都实现了 🐮

之所以选择 奶牛 是因为 具有脚踏实地,任劳任怨的做事风格,同时 奶牛 意味着丰富的营养价值,正如 Fur 所能带给你的。

🍟 文档地址

https://chinadot.net

- + diff --git a/docs/blog/tags/furos/index.html b/docs/blog/tags/furos/index.html index 55999d6fd82..5cb45c2a9cd 100644 --- a/docs/blog/tags/furos/index.html +++ b/docs/blog/tags/furos/index.html @@ -6,7 +6,7 @@ Posts tagged "furos" | Fur - + @@ -25,7 +25,7 @@

1 post tagged with "furos"

View All Tags

Fur 介绍

dotnet中国

dotnet中国

为中国 .NET 开发者提供优质的资讯和技术分享。

star fork GitHub stars GitHub forks GitHub license

Fur.NET 5 平台下极易入门、极速开发的 Web 应用框架。

🍕 名字的由来

故事是这样子的:

起初,想开发一个极易入门、极易维护的框架,开发理念为:一切从简,只为了更懒

所以自然而然想到了:Lazier,也就是 更懒 的意思。但是 更懒更烂 读音相近且中文名没有特色,对此换名问题我苦恼了好几天。

刚好有一次我在博客园中帮一个博友解答问题,解决后博友赞扬我对 .NET Core 颇有了解,我就顺嘴回答了一句:“略懂皮毛”

就这时,脑瓜子灵机一动,干脆起名为:“皮毛”?英文单词 Fur [fɜː(r)]”,单词又短而且中文读音既俗气又顺口。😄😎

所以,Fur 就诞生了。

之后就有了 “小僧不才,略懂皮毛(Fur)。” 广告语 和 chinadot.net 域名。

🍔 关于 LOGO

Fur LOGO 设计由 F U R 三个单词组成:

我相信很多人看到 Fur 的 LOGO 时都会问:“为什么选择奶牛?”,因为 那些年吹过的牛逼都实现了 🐮

之所以选择 奶牛 是因为 具有脚踏实地,任劳任怨的做事风格,同时 奶牛 意味着丰富的营养价值,正如 Fur 所能带给你的。

🍟 文档地址

https://chinadot.net

- + diff --git a/docs/blog/tags/index.html b/docs/blog/tags/index.html index 6cb9f3eef61..222df101db7 100644 --- a/docs/blog/tags/index.html +++ b/docs/blog/tags/index.html @@ -6,7 +6,7 @@ Tags | Fur - + @@ -23,7 +23,7 @@ - + diff --git a/docs/blog/tags/net-5/index.html b/docs/blog/tags/net-5/index.html index 73e6795ae05..1b592e8ba0f 100644 --- a/docs/blog/tags/net-5/index.html +++ b/docs/blog/tags/net-5/index.html @@ -6,7 +6,7 @@ Posts tagged ".net5" | Fur - + @@ -25,7 +25,7 @@

1 post tagged with ".net5"

View All Tags

Fur 介绍

dotnet中国

dotnet中国

为中国 .NET 开发者提供优质的资讯和技术分享。

star fork GitHub stars GitHub forks GitHub license

Fur.NET 5 平台下极易入门、极速开发的 Web 应用框架。

🍕 名字的由来

故事是这样子的:

起初,想开发一个极易入门、极易维护的框架,开发理念为:一切从简,只为了更懒

所以自然而然想到了:Lazier,也就是 更懒 的意思。但是 更懒更烂 读音相近且中文名没有特色,对此换名问题我苦恼了好几天。

刚好有一次我在博客园中帮一个博友解答问题,解决后博友赞扬我对 .NET Core 颇有了解,我就顺嘴回答了一句:“略懂皮毛”

就这时,脑瓜子灵机一动,干脆起名为:“皮毛”?英文单词 Fur [fɜː(r)]”,单词又短而且中文读音既俗气又顺口。😄😎

所以,Fur 就诞生了。

之后就有了 “小僧不才,略懂皮毛(Fur)。” 广告语 和 chinadot.net 域名。

🍔 关于 LOGO

Fur LOGO 设计由 F U R 三个单词组成:

我相信很多人看到 Fur 的 LOGO 时都会问:“为什么选择奶牛?”,因为 那些年吹过的牛逼都实现了 🐮

之所以选择 奶牛 是因为 具有脚踏实地,任劳任怨的做事风格,同时 奶牛 意味着丰富的营养价值,正如 Fur 所能带给你的。

🍟 文档地址

https://chinadot.net

- + diff --git a/docs/blog/tags/net/index.html b/docs/blog/tags/net/index.html index 55698714654..2ded65aa7b3 100644 --- a/docs/blog/tags/net/index.html +++ b/docs/blog/tags/net/index.html @@ -6,7 +6,7 @@ Posts tagged ".net" | Fur - + @@ -25,7 +25,7 @@

1 post tagged with ".net"

View All Tags

Fur 介绍

dotnet中国

dotnet中国

为中国 .NET 开发者提供优质的资讯和技术分享。

star fork GitHub stars GitHub forks GitHub license

Fur.NET 5 平台下极易入门、极速开发的 Web 应用框架。

🍕 名字的由来

故事是这样子的:

起初,想开发一个极易入门、极易维护的框架,开发理念为:一切从简,只为了更懒

所以自然而然想到了:Lazier,也就是 更懒 的意思。但是 更懒更烂 读音相近且中文名没有特色,对此换名问题我苦恼了好几天。

刚好有一次我在博客园中帮一个博友解答问题,解决后博友赞扬我对 .NET Core 颇有了解,我就顺嘴回答了一句:“略懂皮毛”

就这时,脑瓜子灵机一动,干脆起名为:“皮毛”?英文单词 Fur [fɜː(r)]”,单词又短而且中文读音既俗气又顺口。😄😎

所以,Fur 就诞生了。

之后就有了 “小僧不才,略懂皮毛(Fur)。” 广告语 和 chinadot.net 域名。

🍔 关于 LOGO

Fur LOGO 设计由 F U R 三个单词组成:

我相信很多人看到 Fur 的 LOGO 时都会问:“为什么选择奶牛?”,因为 那些年吹过的牛逼都实现了 🐮

之所以选择 奶牛 是因为 具有脚踏实地,任劳任怨的做事风格,同时 奶牛 意味着丰富的营养价值,正如 Fur 所能带给你的。

🍟 文档地址

https://chinadot.net

- + diff --git a/docs/blog/tags/netcore/index.html b/docs/blog/tags/netcore/index.html index 4500cd56eb4..98ccb2df7b3 100644 --- a/docs/blog/tags/netcore/index.html +++ b/docs/blog/tags/netcore/index.html @@ -6,7 +6,7 @@ Posts tagged ".netcore" | Fur - + @@ -25,7 +25,7 @@

1 post tagged with ".netcore"

View All Tags

Fur 介绍

dotnet中国

dotnet中国

为中国 .NET 开发者提供优质的资讯和技术分享。

star fork GitHub stars GitHub forks GitHub license

Fur.NET 5 平台下极易入门、极速开发的 Web 应用框架。

🍕 名字的由来

故事是这样子的:

起初,想开发一个极易入门、极易维护的框架,开发理念为:一切从简,只为了更懒

所以自然而然想到了:Lazier,也就是 更懒 的意思。但是 更懒更烂 读音相近且中文名没有特色,对此换名问题我苦恼了好几天。

刚好有一次我在博客园中帮一个博友解答问题,解决后博友赞扬我对 .NET Core 颇有了解,我就顺嘴回答了一句:“略懂皮毛”

就这时,脑瓜子灵机一动,干脆起名为:“皮毛”?英文单词 Fur [fɜː(r)]”,单词又短而且中文读音既俗气又顺口。😄😎

所以,Fur 就诞生了。

之后就有了 “小僧不才,略懂皮毛(Fur)。” 广告语 和 chinadot.net 域名。

🍔 关于 LOGO

Fur LOGO 设计由 F U R 三个单词组成:

我相信很多人看到 Fur 的 LOGO 时都会问:“为什么选择奶牛?”,因为 那些年吹过的牛逼都实现了 🐮

之所以选择 奶牛 是因为 具有脚踏实地,任劳任怨的做事风格,同时 奶牛 意味着丰富的营养价值,正如 Fur 所能带给你的。

🍟 文档地址

https://chinadot.net

- + diff --git a/docs/blog/welcome/index.html b/docs/blog/welcome/index.html index 09d38c021cc..6a17b355758 100644 --- a/docs/blog/welcome/index.html +++ b/docs/blog/welcome/index.html @@ -6,7 +6,7 @@ Fur 介绍 | Fur - + @@ -24,7 +24,7 @@

Fur 介绍

dotnet中国

dotnet中国

为中国 .NET 开发者提供优质的资讯和技术分享。

star fork GitHub stars GitHub forks GitHub license

Fur.NET 5 平台下极易入门、极速开发的 Web 应用框架。

🍕 名字的由来

故事是这样子的:

起初,想开发一个极易入门、极易维护的框架,开发理念为:一切从简,只为了更懒

所以自然而然想到了:Lazier,也就是 更懒 的意思。但是 更懒更烂 读音相近且中文名没有特色,对此换名问题我苦恼了好几天。

刚好有一次我在博客园中帮一个博友解答问题,解决后博友赞扬我对 .NET Core 颇有了解,我就顺嘴回答了一句:“略懂皮毛”

就这时,脑瓜子灵机一动,干脆起名为:“皮毛”?英文单词 Fur [fɜː(r)]”,单词又短而且中文读音既俗气又顺口。😄😎

所以,Fur 就诞生了。

之后就有了 “小僧不才,略懂皮毛(Fur)。” 广告语 和 chinadot.net 域名。

🍔 关于 LOGO

Fur LOGO 设计由 F U R 三个单词组成:

我相信很多人看到 Fur 的 LOGO 时都会问:“为什么选择奶牛?”,因为 那些年吹过的牛逼都实现了 🐮

之所以选择 奶牛 是因为 具有脚踏实地,任劳任怨的做事风格,同时 奶牛 意味着丰富的营养价值,正如 Fur 所能带给你的。

🍟 文档地址

https://chinadot.net

🌭 开源地址

🍿 Docker 镜像

docker run --name fur -p 5000:80 monksoul/fur:v1.0.0-2020.10.07

🥞 架构设计

正在整理中...

🥝 功能模块

🥐 框架依赖

Fur 为了追求极速入门,极致性能,尽可能的不使用或减少第三方依赖。目前 Fur 仅集成了以下三个依赖:

麻雀虽小五脏俱全。Fur 即使只集成了这三个依赖,但是主流的 依赖注入/控制反转AOP 面向切面编程,事件总线数据验证数据库操作 等等一个都不少。

🥗 环境要求

  • Visual Studio 2019 Preview 16.8 +
  • .NET 5 SDK +
  • .Net Standard 2.1 +

🥪 支持平台

  • 运行环境
    • Windows
    • Linux
    • MacOS
    • Docker/K8S/K3S/Rancher
  • 数据库
    • SqlServer
    • Sqlite
    • Azure Cosmos
    • MySql
    • PostgreSQL
    • InMemoryDatabase
    • Oracle
    • Firebird
    • 达梦数据库
  • 应用部署
    • Kestrel
    • Nginx
    • Jexus
    • IIS
    • Apache
    • PM2
    • Supervisor
    • 单文件
    • 容器(Docker/K8S/K3S/Rancher)

🍖 关于性能

Fur 目前采用 Visual Studio 2019 Preview 16.8 自带性能测试和 JMeter 进行测试,由于篇幅有限,只贴部分测试图,测试结果如下:


🍚 关于作者

一个拥有 12 年开发经验 .NETer。喜欢分享,喜欢新技术,在互联网多个技术领域皆有涉猎。

🍤 项目成员

🎈 欢迎更多的开发者加入 Fur 大家庭。

🍝 谁在使用

  • 百签科技(广东)有限公司
  • 码为科技(广州)有限公司
  • 广州启顺国际货运代理有限公司
  • 森丰供应链服务(广州)有限公司
  • 中山赢友网络科技有限公司
  • 中山模思软件科技有限公司
  • 珠海市恒泰新软件有限责任公司
  • 珠海思诺锐创软件有限公司
  • 深圳市易胜科技有限公司
  • 重庆虫儿飞科技有限公司
  • 重庆林木森科技有限公司

如果您的项目使用到 Fur 开发,可以告诉我们。

🍻 贡献代码

Fur 遵循 Apache-2.0 开源协议,欢迎大家提交 PRIssue

如果要为项目做出贡献,请查看贡献指南。

🍍 捐赠列表

注:排序按捐赠顺序书写

捐赠人昵称捐赠金额(元)附语
🤴 爱吃油麦菜100感谢您的开源项目!
👳‍♂️ 麦壳饼200感谢您的开源项目!
👨 Sun100感谢您的开源项目!
👶 d61761720感谢您的开源项目!
👦 Diqiguoji00816.66见贤思齐
👲 nodyang100感谢您的开源项目!
👳‍♀️ mictxd100吹过的牛都实现。
🧓 欧流全10希望将来超越 Spring
👨‍⚕️ lionkon10...看了框架感觉拿来学习是很不错的...

非常感谢您们的支持,正是因为您们,中国开源才可以越走越远,Fur 越走越远。

🥔 QQ 交流群

🧆 友情链接

👉 Fur 👉 SqlSugar 👉 Layx 👉 t-io

- + diff --git a/docs/docs/aop/index.html b/docs/docs/aop/index.html index dace97c7506..c8a6d7d111a 100644 --- a/docs/docs/aop/index.html +++ b/docs/docs/aop/index.html @@ -6,7 +6,7 @@ 20. 拦截切面 | Fur - + @@ -26,7 +26,7 @@
- + diff --git a/docs/docs/appstartup/index.html b/docs/docs/appstartup/index.html index 6a5c8287ede..08a5a3fdab0 100644 --- a/docs/docs/appstartup/index.html +++ b/docs/docs/appstartup/index.html @@ -4,9 +4,9 @@ -3. 应用启动 | Fur +3. 应用启动 | Fur - + @@ -20,13 +20,38 @@ - +
-
+

3. 应用启动

3.1 Startup

Startup 类是 ASP.NET Core 应用程序启动默认调用的类,该类是在 Program.cs 中配置:

Fur.Web.Entry\Program.cs
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
+
namespace Fur.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>();
});
}
}
}

3.1.1 Startup 两个重要方法

Startup 默认有两个重要的方法:

  • ConfigureServices:配置应用所需服务,在该方法中可以添加应用所需要的功能或服务
  • Configure:配置应用请求处理管道

默认代码如下:

Fur.Web.Entry\Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
+
namespace Fur.Web.Entry
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
}
+
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
}
}
}

在这里,不打算详细讲 Startup 类的具体功能和作用。

了解更多

想了解更多 Startup 知识可查阅 ASP.NET Core - Startup 类 章节。

3.2 AppStartup

Fur 框架中,提供了更为灵活的 Startup 类配置方式,无需在 Web 启用层 中配置,可将配置放到任何项目层。

可能会有读者有疑问,为什么要多此一举呢?原因有几点:

  • Startup 类默认和 Web 应用层 绑定在一起,这样就会导致如果我创建了新的 Web 应用层Startup 又要重新配置
  • 随着业务的增长,需要集成越来越多的第三方服务,这时候 Startup 类就会变得越来越臃肿,难以维护
  • Startup 类无法其他项目类型进行共用

所以,Fur 提供了更加灵活的配置方式:AppStartup

3.2.1 如何配置 AppStartup

AppStartup 是一个抽象的空类,没有任何定义成员。正是因为这样,才提供更加灵活的配置方式。

3.2.2 AppStartup 约定

AppStartup 派生类只有两个小约定:

  • 任何公开、非静态、返回值为 void 且方法第一个参数是 IServiceCollection 类型,那么他就是一个 ConfigureServices 方法
  • 任何公开、非静态、返回值为 void 且方法第一个参数是 IApplicationBuilder 类型,第二个参数是 IWebHostEnvironment 类型,那么他就是一个 Configure 方法

所以,我们可以自由的编写方法,只要遵循约定即可,如:

using Microsoft.Extensions.DependencyInjection;
+
namespace Fur.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.2.3 AppStartup 配置顺序

默认情况下,AppStartup 配置顺序由所在程序集的名称进行正序调用,如果我们需要配置执行顺序,只需要在 AppStartup 派生类中贴 [AppStartup(order)] 特性即可。

order 数值越大,约在前面调用,如:

using Microsoft.Extensions.DependencyInjection;
+
namespace Fur.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 Fur.EntityFramework.Core
{
[AppStartup(9)]
public class SecondStartup : AppStartup
{
public void ConfigureServices(IServiceCollection services)
{
}
+
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
}
}
}

FirstStartup 会在 SecondStartup 之前调用。

3.2.4 AppStartup 方法调用顺序

AppStartup 方法调用顺序和方法的书写先后有关,越在前面的方法越先调用。

3.3 框架默认 AppStartup 实现

Fur 框架默认在每一个项目层中都创建了一个 AppStartup 派生类,方便大家配置。如:

  • FurStartup.csFur 框架核心启动类(通常无需配置)
  • FurApplicationStartup.cs:业务服务启动类
  • FurCoreStartup.cs:应用核心功能启动类
  • FurEntityFrameworkCoreStartup.cs:数据库相关启动类
  • FurWebCoreStartup.csWeb 核心启动配置类

3.4 Startup 配置最佳实践

建议 Web 启动层的 Startup.cs 保持为空方法体,如:

Fur.Web.Entry\Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
+
namespace Fur.Web.Entry
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
}
+
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
}
}
}

将所有 Web 应用层 配置迁移到 FurWebCoreStartup.cs 中,如:

Fur.Web.Core\FurWebCoreStartup.cs
using Fur.UnifyResult;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
+
namespace Fur.Web.Core
{
[AppStartup(800)]
public sealed class FurWebCoreStartup : AppStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddCorsAccessor();
+
services.AddSpecificationDocuments();
services.AddControllers()
.AddDynamicApiControllers()
.AddDataValidation()
.AddFriendlyException()
.AddUnifyResult<RESTfulResult, RESTfulResultProvider>();
}
+
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
+
app.UseHttpsRedirection();
+
app.UseRouting();
+
app.UseCorsAccessor();
+
app.UseAuthentication();
app.UseAuthorization();
+
app.UseSpecificationDocuments();
+
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}

这样,后续更换 Web 应用层 也无需重新配置 Startup.cs

3.5 关于 appsettings.json

在默认情况下,ASP.NET Core 配置放在 appsettings.json 中配置,但是这样的方式和 Startup.cs 配置一样的道理,一旦我们更换了 Web 应用层,那么 appsettings.json 又要重新配置一次。

所以,Fur 框架提供了更加灵活的方式配置 appsettings.json只需要在任何项目层根目录下创建 .json 文件即可

Fur 框架最后会自动合并所有分散的配置文件。

如我们在 Fur.EntityFramework.Core 层创建 dbsettings.json 配置数据库连接字符串,如:

Fur.EntityFramework.Core\dbsettings.json
{
"ConnectionStrings": {
"DbConnectionString": "Server=localhost;Database=Fur;User=sa;Password=000000;MultipleActiveResultSets=True;",
"Sqlite3ConnectionString": "Data Source=./Fur.db"
}
}

无需在 appsettings.json 中配置,下面是 appsettings.json 默认代码:

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information",
"Microsoft.EntityFrameworkCore": "Information"
}
},
"AllowedHosts": "*"
}

这样我们把配置文件分散在不同项目层之后,就可以实现共用和共享了。

3.6 神奇的 Inject()

Inject() 方法是 Fur 框架提供的最小侵入式的方法,可以让任何 ASP.NET Core Web项目瞬间支持所有 Fur 框架特性。

我们创建了新的 Web 项目,只需要两个步骤即可:

  • 添加 Fur.Web.Core 项目引用
  • Program.cs 中调用即可

如:

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
+
namespace Fur.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>();
});
}
}
}

非常简单吧。我们后续创建任何 MVCRazorPagesBlazor 项目只需要添加 Fur.Web.Core 引用和调用 Inject() 即可。

3.7 反馈与建议

与我们交流

给 Fur 提 Issue

- + @@ -40,6 +65,6 @@ - + \ No newline at end of file diff --git a/docs/docs/auth-control/index.html b/docs/docs/auth-control/index.html index 48e6b61543a..6b080303622 100644 --- a/docs/docs/auth-control/index.html +++ b/docs/docs/auth-control/index.html @@ -6,7 +6,7 @@ 14. 安全鉴权 | Fur - + @@ -26,7 +26,7 @@
- + diff --git a/docs/docs/author/index.html b/docs/docs/author/index.html index ca8ef482dfb..22160804cd4 100644 --- a/docs/docs/author/index.html +++ b/docs/docs/author/index.html @@ -6,7 +6,7 @@ 1.3 关于作者 | Fur - + @@ -26,7 +26,7 @@

1.3 关于作者

互联网账号

  • 百小僧
  • Monk/MonkSoul

技术能力

自 2008 年 接触 IT 这个行业也有十余年了,在 后端(.NET/.NET Core/Java/PHP)、移动端(Xamarin/小程序/Java/Objective-C)、桌面端(WinForm/WPF/Electron)、前端(React/Vue/Angular/Node)等主流领域略知一二。

同时在技术培训领域也多有涉足。

职业情况

目前经营一家自己创办的软件科技公司,主要销售自主研发的 ERP 产品。

吃不起饭的时候也会接外包项目。

兴趣爱好

是个吃货,喜欢看抖音,看动漫,看美剧,看博客园、看开源中国。

对新技术颇感兴趣,喜欢开源事业,喜欢分享技术。

个人主页

https://gitee.com/monksoul

https://github.com/monksoul

- + diff --git a/docs/docs/cache/index.html b/docs/docs/cache/index.html index d795fa6a15b..83d445840d9 100644 --- a/docs/docs/cache/index.html +++ b/docs/docs/cache/index.html @@ -6,7 +6,7 @@ 13. 分布式缓存 | Fur - + @@ -26,7 +26,7 @@
- + diff --git a/docs/docs/configuration/index.html b/docs/docs/configuration/index.html index d79539e2072..4f08b4de7dc 100644 --- a/docs/docs/configuration/index.html +++ b/docs/docs/configuration/index.html @@ -6,7 +6,7 @@ 4.1 配置 | Fur - + @@ -29,7 +29,7 @@
namespace Fur.Web.Entry
{
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
// 启动自动扫描配置文件并注入,无需手动添加配置
.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, nameof(Fur))
.UseStartup<Startup>();
});
}
}

读取 emailsetting.json 配置

读取自定义配置文件和读取 appsettings.json 一致,系统会自动从多个配置文件中读取输入,如:

var smtpServer = App.Configuration["outlook:smtp:server"]; // => smtp.office365.com

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["AppInfo"];
ChangeToken.OnChange(() => appInfoConfiguration.GetReloadToken(), () =>
{
var name = appInfoConfiguration["Name"]; // 实时的最新值
var version = appInfoConfiguration["Version"]; // 实时的最新值
});

4.1.7 配置的优缺点

优点

  • 能够在系统运行时快速读取
  • 无需额外配置

缺点

  • 存在重复读取
  • 通过硬编码字符串读取,容易出错
  • 不能设置默认值
  • 不能在运行环境中动态配置
  • 不能验证配置有效性
  • 不支持更改通知

4.1.8 配置使用场景

如果只需要一次性读取配置信息,则使用配置,否则应该使用 《4.2 选项》代替。

4.1.9 反馈与建议

与我们交流

给 Fur 提 Issue


了解更多

想了解更多 配置 知识可查阅 ASP.NET Core - 配置 章节。

- + diff --git a/docs/docs/contribute/index.html b/docs/docs/contribute/index.html index 17a29e7ebc4..6224a28e548 100644 --- a/docs/docs/contribute/index.html +++ b/docs/docs/contribute/index.html @@ -6,7 +6,7 @@ 28. 贡献指南 | Fur - + @@ -26,7 +26,7 @@ - + diff --git a/docs/docs/cors/index.html b/docs/docs/cors/index.html index cbee2545107..8885bf92f52 100644 --- a/docs/docs/cors/index.html +++ b/docs/docs/cors/index.html @@ -6,7 +6,7 @@ 15. CORS 跨域 | Fur - + @@ -26,7 +26,7 @@
- + diff --git a/docs/docs/data-validation/index.html b/docs/docs/data-validation/index.html index 064cdae0b07..98c583a175d 100644 --- a/docs/docs/data-validation/index.html +++ b/docs/docs/data-validation/index.html @@ -6,7 +6,7 @@ 8. 数据校验 | Fur - + @@ -78,7 +78,7 @@
namespace Fur.Application
{
public class FurAppService : IDynamicApiController
{
[TypeFilter(typeof(DataValidationFilter))]
public TestDto Post(TestDto testDto)
{
return testDto;
}
}
}

8.9.4 [ApiController] 控制器范围验证

[ApiController]Mvc 提供的控制器范围(含所有动作方法)的验证。

using Microsoft.AspNetCore.Mvc;
namespace Fur.Web.Entry.Controllers
{
[ApiController]
public class MvcController : Controller
{
public IActionResult Index()
{
return View();
}
}
}

8.10 MiniProfiler 查看

如下图所示:

8.10 多语言支持

文档整理中...

8.11 验证模型提供器

文档整理中...

8.12 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/dbcontext-Interceptor/index.html b/docs/docs/dbcontext-Interceptor/index.html index 923f8117786..de7da01522f 100644 --- a/docs/docs/dbcontext-Interceptor/index.html +++ b/docs/docs/dbcontext-Interceptor/index.html @@ -6,7 +6,7 @@ 9.24 数据库操作拦截器 | Fur - + @@ -20,11 +20,11 @@ - +
-

9.24 数据库操作拦截器

9.24.1 数据库拦截器

Fur 框架提供三种数据库操作拦截器,可以通过拦截器动态修改数据库连接字符串,动态修改sql,动态更改参数等操作。

目前支持这三种拦截器:

  • DbConnectionInterceptor:数据库连接拦截器
  • DbCommandInterceptor:数据库执行 Sql 拦截器
  • SaveChangesInterceptor:提交到数据库拦截器

9.24.2 支持拦截类型

9.24.2.1 DbConnectionInterceptor

using Microsoft.EntityFrameworkCore.Diagnostics;
using System.Data.Common;
using System.Threading;
using System.Threading.Tasks;
+

9.24 数据库操作拦截器

9.24.1 数据库拦截器

Fur 框架提供三种数据库操作拦截器,可以通过拦截器动态修该数据库连接字符串,动态修改sql,动态更改参数等操作。

目前支持这三种拦截器:

  • DbConnectionInterceptor:数据库连接拦截器
  • DbCommandInterceptor:数据库执行 Sql 拦截器
  • SaveChangesInterceptor:提交到数据库拦截器

9.24.2 支持拦截类型

9.24.2.1 DbConnectionInterceptor

using Microsoft.EntityFrameworkCore.Diagnostics;
using System.Data.Common;
using System.Threading;
using System.Threading.Tasks;
namespace Fur.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);
}
@@ -59,7 +59,7 @@
// 提交数据库失败
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.3 注册自定义过滤器

定义好过滤器之后,我们需要在数据库上下文中注册:

services.AddSqlitePool<FurDbContext>(interceptors: new IInterceptor[] {
new SqlConnectionProfilerInterceptor(),
new DbContextSaveChangesInterceptor(),
new SqlCommandProfilerInterceptor()
});

9.24.4 反馈与建议

与我们交流

给 Fur 提 Issue

- + @@ -73,6 +73,6 @@ - + \ No newline at end of file diff --git a/docs/docs/dbcontext-add-or-update/index.html b/docs/docs/dbcontext-add-or-update/index.html index 71d9b022224..4cdbe4fb23c 100644 --- a/docs/docs/dbcontext-add-or-update/index.html +++ b/docs/docs/dbcontext-add-or-update/index.html @@ -6,7 +6,7 @@ 9.7 新增或更新操作 | Fur - + @@ -104,7 +104,7 @@
// 示例七
await user.InsertOrUpdateExcludeNowAsync(new[] { u=>u.Name, u=>u.Age});
// 示例八
await user.InsertOrUpdateExcludeNowAsync(new[] {"Age", "Name"});

9.5.7 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/dbcontext-add/index.html b/docs/docs/dbcontext-add/index.html index 71166141d5a..7b1c9c8289d 100644 --- a/docs/docs/dbcontext-add/index.html +++ b/docs/docs/dbcontext-add/index.html @@ -6,7 +6,7 @@ 9.5 新增操作 | Fur - + @@ -55,7 +55,7 @@
// 示例二
await repository.InsertNowAsync(new List<User> { user, user2 });
// 示例三
await repository.InsertNowAsync(new[] {user, user2 });
小知识

所有带 Now 结尾的表示立即提交到数据库,也就是立即调用 SaveChangesSaveChangesAsync

9.5.5 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/dbcontext-audit/index.html b/docs/docs/dbcontext-audit/index.html index c6fa84c9bd9..b5f798a997e 100644 --- a/docs/docs/dbcontext-audit/index.html +++ b/docs/docs/dbcontext-audit/index.html @@ -6,7 +6,7 @@ 9.22 审计日志 | Fur - + @@ -39,7 +39,7 @@
object oldValue = null;
// 如果是新增数据,则 databaseValues 为空,所以需要判断一下
if (databaseValues != null)
{
oldValue = databaseValues[propName];
}
// 插入审计日志表
dbContext.Audits.Add(new Audit
{
Table = entityType.Name, // 表名
Column = propName, // 更新的列
NewValue = newValue, // 新值
OldValue = oldValue, // 旧值
CreatedTime = DateTime.Now, // 操作时间
UserId = userId, // 操作人
Operate = entity.State.ToString(); // 操作方式:新增、更新、删除
});
}
}
}
}
}
小知识

如果对性能有所要求,那么建议审计日志通过 日志组件 写入数据库,如,通过 Nlog、Log4Net 这些等:

// 插入审计日志表
dbContext.Audits.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.4 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/dbcontext-batch/index.html b/docs/docs/dbcontext-batch/index.html index 01d386f3674..51bd41e7c0a 100644 --- a/docs/docs/dbcontext-batch/index.html +++ b/docs/docs/dbcontext-batch/index.html @@ -6,7 +6,7 @@ 9.9 批量操作 | Fur - + @@ -34,7 +34,7 @@
// 根据条件批量更新
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 批量操作性能

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 反馈与建议

与我们交流

给 Fur 提 Issue


了解更多

想了解更多 EFCore.BulkExtensions 知识可查阅 EFCore.BulkExtensions 开源仓库

- + diff --git a/docs/docs/dbcontext-code-first/index.html b/docs/docs/dbcontext-code-first/index.html index 1c4f2d7977b..ad9bf2447ba 100644 --- a/docs/docs/dbcontext-code-first/index.html +++ b/docs/docs/dbcontext-code-first/index.html @@ -6,7 +6,7 @@ 9.20 模型生成数据库 | Fur - + @@ -30,7 +30,7 @@
/// <summary>
/// 年龄
/// </summary>
public int Age { get; set; }
/// <summary>
/// 住址
/// </summary>
public string Address { get; set; }
}
}
实体约定

所有数据库实体必须直接或间接继承 IEntity 接口。

9.20.2.2 打开 程序包管理控制台

9.20.2.3 切换默认项目

程序包管理控制台 默认项目设置为 Fur.Database.Migrations

9.20.2.4 创建模型版本

Add-Migration v1.0.0
特别说明

v1.0.0 是此处数据库更改的版本号,可以写任何字符串,但推荐写版本号,每次 +1

最终命令如下:

PM> Add-Migration v1.0.0
Build 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 'FurDbContext' using provider 'Microsoft.EntityFrameworkCore.Sqlite' with options: SensitiveDataLoggingEnabled DetailedErrorsEnabled MaxPoolSize=100 MigrationsAssembly=Fur.Database.Migrations
To undo this action, use Remove-Migration.
PM>

生成成功后,Fur.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 反馈与建议

与我们交流

给 Fur 提 Issue


了解更多

想了解更多 正向工厂 知识可查阅 EF Core - 管理数据库架构 章节。

- + diff --git a/docs/docs/dbcontext-db-first/index.html b/docs/docs/dbcontext-db-first/index.html index 3d77e8addd5..aee98ee5914 100644 --- a/docs/docs/dbcontext-db-first/index.html +++ b/docs/docs/dbcontext-db-first/index.html @@ -6,7 +6,7 @@ 9.19 数据库生成模型 | Fur - + @@ -56,7 +56,7 @@
}
}
Fur Tools v1.0.0 全部实体生成成功!
PM>

9.13.4 命令参数配置

Fur Tools Cli 支持多个参数配置,使用方法只需要在命令后面添加即可,如:

&"../tools/cli.ps1" -Context 数据库上下文名 -ConnectionName 连接字符串Key

支持参数如下:

  • -Tables:配置要生成的数据库表,数组类型,如果为空,则生成数据库所有表和视图。如:-Tables Person,PersonDetails
  • -Context:配置数据库上下文,默认 FurDbContext,如果有多个数据库上下文,则此参数必须配置
  • -ConnectionName:配置数据库连接字符串,对于 appsetting.json 中的 Key
  • -OutputDir:生成实体代码输出目录,默认为:./Fur.Core/Entities/
  • -DbProvider:数据库提供器,默认是 Microsoft.EntityFrameworkCore.SqlServer,其他数据库请指定对应程序集
    • SqlServerMicrosoft.EntityFrameworkCore.SqlServer
    • SqliteMicrosoft.EntityFrameworkCore.Sqlite
    • CosmosMicrosoft.EntityFrameworkCore.Cosmos
    • InMemoryDatabaseMicrosoft.EntityFrameworkCore.InMemory
    • MySqlPomelo.EntityFrameworkCore.MySql
    • PostgreSQLNpgsql.EntityFrameworkCore.PostgreSQL
    • OracleCitms.EntityFrameworkCore.Oracle
  • -EntryProject:Web 启用项目层名,默认 Fur.Web.Entry
  • -CoreProject:实体项目层名,默认 Fur.Core
  • -DbContextLocators:多数据库上下文定位器,默认 MasterDbContextLocator,支持多个,如:MasterDbContextLocator,MySqlDbContextLocator
  • -Product:解决方案默认前缀,如 Fur

9.13.5 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/dbcontext-delete/index.html b/docs/docs/dbcontext-delete/index.html index e70a87153bf..5c1c23b3a16 100644 --- a/docs/docs/dbcontext-delete/index.html +++ b/docs/docs/dbcontext-delete/index.html @@ -6,7 +6,7 @@ 9.8 删除操作 | Fur - + @@ -71,7 +71,7 @@
// 示例五
await entity.FakeDeleteAsync();
// 示例六
await repository.UpdateIncludeAsync(user, u => u.IsDeleted);

9.8.9 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/dbcontext-filter/index.html b/docs/docs/dbcontext-filter/index.html index 7835fbd0b6d..151fae924cd 100644 --- a/docs/docs/dbcontext-filter/index.html +++ b/docs/docs/dbcontext-filter/index.html @@ -6,7 +6,7 @@ 9.23 实体/全局查询筛选器 | Fur - + @@ -38,7 +38,7 @@
// 创建表达式元素
var parameter = Expression.Parameter(metadata.ClrType, "u");
var properyName = Expression.Constant(nameof(Entity.IsDeleted));
var propertyValue = Expression.Constant(false);
// 构建表达式 u => EF.Property<bool>(u, "IsDeleted") == false
var expressionBody = Expression.Equal(Expression.Call(typeof(EF), nameof(EF.Property), new[] { typeof(bool) }, parameter, properyName), propertyValue);
var expression = Expression.Lambda(expressionBody, parameter);
return expression;
}
}
}
小建议

如果对动态构建 LambdaExpression 不熟悉的朋友,可以使用 System.Linq.Dynamic.Corehttps://github.com/zzzprojects/System.Linq.Dynamic.Core

9.23.3 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/dbcontext-function/index.html b/docs/docs/dbcontext-function/index.html index 3c7b6b65442..f77d2154ccc 100644 --- a/docs/docs/dbcontext-function/index.html +++ b/docs/docs/dbcontext-function/index.html @@ -6,7 +6,7 @@ 9.14 函数操作 | Fur - + @@ -50,7 +50,7 @@
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("Fur")).ToList();

最终生成 Sql

SELECT [g].Id, [g].Name, [g].Age, [g].Address
FROM dbo.GetPersons(1) AS [g]
WHERE [g].Name == N'Fur';

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 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/dbcontext-hight-query/index.html b/docs/docs/dbcontext-hight-query/index.html index 8b3e45371fd..a28da048665 100644 --- a/docs/docs/dbcontext-hight-query/index.html +++ b/docs/docs/dbcontext-hight-query/index.html @@ -6,7 +6,7 @@ 9.11 高级查询操作 | Fur - + @@ -57,7 +57,7 @@
namespace Fur.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<City> 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.12 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/dbcontext-locator/index.html b/docs/docs/dbcontext-locator/index.html index 0a80ac8df5c..7f3fe0a169a 100644 --- a/docs/docs/dbcontext-locator/index.html +++ b/docs/docs/dbcontext-locator/index.html @@ -6,7 +6,7 @@ 9.2 数据库上下文定位器 | Fur - + @@ -28,7 +28,7 @@
namespace Fur.Core
{
public sealed class FurDbContextLocator : IDbContextLocator
{
}
}

9.2.4 默认数据库上下文定位器

Fur 框架中已经提供了 MasterDbContextLocator 默认数据库上下文定位器,所以默认数据库上下文只需继承 AppDbContext<TDbContext> 即可。

AppDbContext<TDbContext> 定义代码如下:

using Fur.DependencyInjection;
using Microsoft.EntityFrameworkCore;
namespace Fur.DatabaseAccessor
{
/// <summary>
/// 默认应用数据库上下文
/// </summary>
/// <typeparam name="TDbContext">数据库上下文</typeparam>
[NonBeScan]
public abstract class AppDbContext<TDbContext> : AppDbContext<TDbContext, MasterDbContextLocator>
where TDbContext : DbContext
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="options"></param>
public AppDbContext(DbContextOptions<TDbContext> options) : base(options)
{
}
}
}

9.2.5 数据库上下文定位器支持对象

目前数据库上下文支持以下多个对象:

  • AppDbContext<TEntity, TDbContextLocator>:数据上下文
  • IRepository<TEntity, TDbContextLocator:实体仓储
  • ISqlRepository<TDbContextLocator>: Sql 操作仓储
  • Func<Type, DbContext>:依赖注入获取数据库上下文
  • Entity<Tkey, TDbContextLocator> :实体配置
  • EntityBase<Tkey, TDbContextLocator1, ... TDbContextLocator8>:实体配置
  • EntityNotKey<TDbContextLocator1, ... TDbContextLocator8>:无键实体配置
  • IEntitySeedData<TEntity, TDbContextLocator1, ... TDbContextLocator8>:种子数据配置
  • IEntityTypeBuilder<TEntity, TDbContextLocator1, ... TDbContextLocator8>:实体类型构建器
  • IModelBuilderFilter<TDbContextLocator1, ... TDbContextLocator8>:模型构建筛选器
  • [QueryableFunction(DbContextLocators=Type[])]:查询函数

9.2.6 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/dbcontext-multi-database/index.html b/docs/docs/dbcontext-multi-database/index.html index c3acd394145..f24d0b3d8a4 100644 --- a/docs/docs/dbcontext-multi-database/index.html +++ b/docs/docs/dbcontext-multi-database/index.html @@ -6,7 +6,7 @@ 9.18 多数据库操作 | Fur - + @@ -43,7 +43,7 @@
// 支持一个数据库
public class Person: IEntity<MySqlDbContextLocator>
{
// ....
}
// 支持多个数据库
public class Person: IEntity<MySqlDbContextLocator, SqliteDbContextLocator>
{
// ....
}
小知识

所有的 实体依赖接口或抽象类 都支持泛型方式 指定 数据库上下文定位器,最多支持 8 个。

9.18.3.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.4 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/dbcontext-proc/index.html b/docs/docs/dbcontext-proc/index.html index 6b0aeddc962..1e3c717063e 100644 --- a/docs/docs/dbcontext-proc/index.html +++ b/docs/docs/dbcontext-proc/index.html @@ -6,7 +6,7 @@ 9.13 存储过程操作 | Fur - + @@ -119,7 +119,7 @@
// 获取 RETURN 返回值
var reval = result.ReturnValue;
// 获取返回结果集
var (list1,list2) = result.Result;
关于异步

Fur 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

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 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/dbcontext-query/index.html b/docs/docs/dbcontext-query/index.html index 74186bd9875..d1a4c398421 100644 --- a/docs/docs/dbcontext-query/index.html +++ b/docs/docs/dbcontext-query/index.html @@ -6,7 +6,7 @@ 9.10 查询操作 | Fur - + @@ -138,7 +138,7 @@
// 示例二
_testRepository.Where(u => u.Name.EndWith("Fur"));
// 示例三
_testRepository.Where(u => u.Name.Contains("Fur"));

9.10.6.9 Case When

数据库中的 Case When 实际上对应的是我们程序中的 三元表达式 ,也就是使用 三元表达式 即可自动生成 Case When 语句。

9.10.7 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/dbcontext-read-write/index.html b/docs/docs/dbcontext-read-write/index.html index 4f054075918..9e473c10e2e 100644 --- a/docs/docs/dbcontext-read-write/index.html +++ b/docs/docs/dbcontext-read-write/index.html @@ -6,7 +6,7 @@ 9.26 读写分离/主从复制 | Fur - + @@ -20,7 +20,7 @@ - +
@@ -28,7 +28,7 @@
namespace Fur.EntityFramework.Core
{
/// <summary>
/// 主库数据库上下文
/// </summary>
[AppDbContext("MasterConnectionString")]
public class MasterDbContext : AppDbContext<MasterDbContext>
{
public MasterDbContext(DbContextOptions<MasterDbContext> options) : base(options)
{
}
}
}

数据库连接字符串:

{
"ConnectionStrings": {
"MasterConnectionString": "Server=localhost;Database=Fur;User=sa;Password=000000;MultipleActiveResultSets=True;"
}
}

9.26.2.2 创建 从库 数据库上下文

using Fur.Core;
using Fur.DatabaseAccessor;
using Microsoft.EntityFrameworkCore;
namespace Fur.EntityFramework.Core
{
/// <summary>
/// 从库数据库上下文
/// </summary>
[AppDbContext("SlaveConnectionString")]
public class SlaveDbContext : AppDbContext<SlaveDbContext, SlaveDbContextLocator>
{
public SlaveDbContext(DbContextOptions<SlaveDbContext> options) : base(options)
{
}
}
}
特别注意

多数据库操作除了默认数据库无需自定义 数据库上下文定位器,其他数据库都需要有数据库上下文定位器。如 SlaveDbContextLocator

从库数据库上下文定位器:

using Fur.DatabaseAccessor;
namespace Fur.Core
{
/// <summary>
/// 从库数据库上下文定位器
/// </summary>
public class SlaveDbContextLocator : IDbContextLocator
{
}
}

数据库连接字符串:

{
"ConnectionStrings": {
"SlaveConnectionString": "Server=localhost;Database=FurSlave;User=sa;Password=000000;MultipleActiveResultSets=True;"
}
}

9.26.2.3 注册 主从库 数据库上下文

using Fur.Core;
using Microsoft.Extensions.DependencyInjection;
-
namespace Fur.EntityFramework.Core
{
[Startup(600)]
public sealed class FurEntityFrameworkCoreStartup : AppStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddDatabaseAccessor(options =>
{
services.AddSqlServerPool<MasterDbContext>();
services.AddSqlServerPool<SlaveDbContext, SlaveDbContextLocator>();
});
}
}
}

9.26.2.4 创建 Person 实体

由于 主从库 具有相同的数据库结构,所以实体也必须声明 主从库

using Fur.DatabaseAccessor;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
+
namespace Fur.EntityFramework.Core
{
[AppStartup(600)]
public sealed class FurEntityFrameworkCoreStartup : AppStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddDatabaseAccessor(options =>
{
services.AddSqlServerPool<MasterDbContext>();
services.AddSqlServerPool<SlaveDbContext, SlaveDbContextLocator>();
});
}
}
}

9.26.2.4 创建 Person 实体

由于 主从库 具有相同的数据库结构,所以实体也必须声明 主从库

using Fur.DatabaseAccessor;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Fur.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.26.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.26.2.6 使用例子

using Fur.Core;
using Fur.DatabaseAccessor;
using Fur.DynamicApiController;
using System.Collections.Generic;
@@ -38,7 +38,7 @@
/// <summary>
/// 查询走从库
/// </summary>
/// <returns></returns>
public List<Person> Get()
{
return _msRepository.Slave1<Person>().AsEnumerable();
}
}
}

9.26.3 主从复制

主从复制:是一种数据备份的方案。

简单来说,是使用两个或两个以上相同的数据库,将一个数据库当做主数据库,而另一个数据库当做从数据库。在主数据库中进行相应操作时,从数据库记录下所有主数据库的操作,使其二者一模一样。

9.26.4 主从复制几种方式

9.26.4.1 同步复制

所谓的同步复制,意思是 Master 的变化,必须等待 Slave-1,Slave-2,...,Slave-n 完成后才能返回。 这样,显然不可取,比如,在 Web 前端页面上,用户增加了条记录,需要等待很长时间。

9.26.4.2 异步复制

如同 AJAX 请求一样。Master 只需要完成自己的数据库操作即可。至于 Slaves 是否收到二进制日志,是否完成操作,不用关心。(推荐方式)

9.26.4.3 半同步复制

Master 只保证 Slaves 中的一个操作成功,就返回,其他 Slave 不管。

下面将使用 SqlServer 简单配置主从复制功能。

9.26.5 SqlServer 主库配置

9.26.5.1 添加 本地发布

9.26.5.2 选择 分发服务器

9.26.5.3 启用 代理

9.26.5.4 发布数据库

9.26.5.5 快照发布

具体选择何种发布类型,视具体业务场景而定。

9.26.5.6 选择发布项目

9.26.5.7 配置分发计划

9.26.5.8 配置安全设置

9.26.5.9 完成配置

9.26.6 SqlServer 从库配置

9.26.6.1 添加 本地订阅

9.26.6.2 选择 分发服务器

9.26.6.3 选择 分发代理位置

9.26.6.4 选择 订阅数据库

9.26.6.5 选择 分发安全设置

9.26.6.6 选择 同步计划

9.26.6.7 完成订阅

9.26.7 分发定义监视

9.26.8 查看主从复制结果

特别特性

主从复制有一定迟延性,所以系统设计要有一定“容忍性"。

9.26.9 反馈与建议

与我们交流

给 Fur 提 Issue

- + @@ -52,6 +52,6 @@ - + \ No newline at end of file diff --git a/docs/docs/dbcontext-repository/index.html b/docs/docs/dbcontext-repository/index.html index 50e8f1d813b..d5a8e255b22 100644 --- a/docs/docs/dbcontext-repository/index.html +++ b/docs/docs/dbcontext-repository/index.html @@ -6,7 +6,7 @@ 9.4 仓储模式 | Fur - + @@ -33,7 +33,7 @@
// 其他更多数据库一样的操作

另外任何仓储或实体配置都支持多个数据库同时操作

仓储方式

IRepository<Person, MsSqlDbContextLocator> mssqlRepository
ISqlRepository<MsSqlDbContextLocator> mssqlRepository;

动态 sql 方式

"select * from person".Change<MsSqlDbContextLocator>().SqlQuery();

实体配置方式

public class User:Entity<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.5 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/dbcontext-seed-data/index.html b/docs/docs/dbcontext-seed-data/index.html index bd7fb38caa6..2f21c3110a6 100644 --- a/docs/docs/dbcontext-seed-data/index.html +++ b/docs/docs/dbcontext-seed-data/index.html @@ -6,7 +6,7 @@ 9.21 实体种子数据 | Fur - + @@ -32,7 +32,7 @@
namespace Fur.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 多个数据库种子数据

Fur 提供泛型的方式支持多个数据库种子数据设定,如:

using Fur.DatabaseAccessor;
using System.Collections.Generic;
namespace Fur.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 反馈与建议

与我们交流

给 Fur 提 Issue


了解更多

想了解更多 数据种子 知识可查阅 EF Core - 数据种子设定 章节。

- + diff --git a/docs/docs/dbcontext-sql-proxy/index.html b/docs/docs/dbcontext-sql-proxy/index.html index 5d48c56c353..051c7b8d8a1 100644 --- a/docs/docs/dbcontext-sql-proxy/index.html +++ b/docs/docs/dbcontext-sql-proxy/index.html @@ -6,7 +6,7 @@ 9.17 Sql 高级代理 | Fur - + @@ -76,7 +76,7 @@
namespace Fur.Application
{
public interface ISql : ISqlDispatchProxy
{
[SqlFunction("FN_Name")] // 标量函数
string GetValue(MyParam dto);
[SqlProcedure("FN_Name")] // 表值函数
List<Person> GetPersons(int id);
}
}
补充说明

Sql 代理会自动判断返回值然后自动执行特定函数类型。

9.17.6 为什么用它?

通过上面的例子大家就可以了解,这种方式操作 sql 非常简单,而且极易维护。大家不用去关系返回值,关心用哪个方法,所有东西会自动给你处理好。

所以,如果需要用 Sql 操作,推荐使用 Sql 高级代理。

9.17.7 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/dbcontext-sql-template/index.html b/docs/docs/dbcontext-sql-template/index.html index 1196186926d..a4eebb70c07 100644 --- a/docs/docs/dbcontext-sql-template/index.html +++ b/docs/docs/dbcontext-sql-template/index.html @@ -6,7 +6,7 @@ 9.16 Sql 模板 | Fur - + @@ -28,7 +28,7 @@
// 懒人方式
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 u
left join #(User.Detail) d on u.Id = d.UserId
where id > @id");

9.16.4 Sql 模板配置

9.16.4.1 普通模式

{
"Select.User": "select * from User"
}

9.16.4.2 更多配置

{
"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 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/dbcontext-sql/index.html b/docs/docs/dbcontext-sql/index.html index 1199fc2bcd7..19e552e70a4 100644 --- a/docs/docs/dbcontext-sql/index.html +++ b/docs/docs/dbcontext-sql/index.html @@ -6,7 +6,7 @@ 9.15 Sql 操作 | Fur - + @@ -173,7 +173,7 @@
// 不再举例子。。。。。。
补充说明

不管是那种方式操作 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.6 IRepository 操作

IRepository 也能操作 sql,调用方法也是和上面一致的,如:

var dataTable = repository.Sql().SqlQuery("select * from person");
特别说明

由于篇幅有限,不再列举所有例子。

9.15.7 IRepository<TEntity> 操作

IRepository<TEntity> 也能操作 sql,调用方法也是和上面一致的,如:

var dataTable = personRepository.SqlQuery("select * from person");
特别说明

由于篇幅有限,不再列举所有例子。

9.15.8 关于 Sql 参数

所有 sql存储过程函数 参数都支持四种方式:

  • DbParameter[]:数组类型
  • new {}:匿名类型
  • new Class{}:强类型类型(支持复杂存储过程参数)
  • Dictionary<string,object> 类型
小知识

建议除了复杂的存储过程(带 OUTPUT/RETURN)的以外,所有参数建议使用 new {} 匿名类型,如果需要动态参数,则可以使用 Dictionary<string,object> 类型。

9.15.9 多数据库 Sql 操作 💯 💛

Fur 框架拥有非常灵活的多数据库操作方式,只需通过多数据库上下文定位器即可动态切换数据库。

9.15.9.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.9.2 ISqlRepository 方式

只需要通过 ISqlRepository<TDbContextLocator> 注入或通过 sqlRepository.Change<TDbContextLocator>() 切换。

9.15.9.3 IRepository 方式

只需要通过 repository.Change<TDbContextLocator>() 获取即可。

9.15.9.4 IRepository<TEntity> 方式

只需要通过 IRepository<TEntity, TDbContextLocator> 注入或通过 personRepository.Change<TEntity, TDbContextLocator>() 切换。

9.15.10 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/dbcontext-update/index.html b/docs/docs/dbcontext-update/index.html index fb8287eef05..8743a368981 100644 --- a/docs/docs/dbcontext-update/index.html +++ b/docs/docs/dbcontext-update/index.html @@ -6,7 +6,7 @@ 9.6 更新操作 | Fur - + @@ -198,7 +198,7 @@
// 示例二
await repository.UpdateNowAsync(new List<User> { user, user2 });
// 示例三
await repository.UpdateNowAsync(new[] {user, user2 });
小知识

所有带 Now 结尾的表示立即提交到数据库,也就是立即调用 SaveChangesSaveChangesAsync

9.6.15 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/dbcontext-view/index.html b/docs/docs/dbcontext-view/index.html index d087ae7fc8d..d05add21587 100644 --- a/docs/docs/dbcontext-view/index.html +++ b/docs/docs/dbcontext-view/index.html @@ -6,7 +6,7 @@ 9.12 视图操作 | Fur - + @@ -34,7 +34,7 @@
public FurService(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.AsAsyncEnumerable();
return list;
}
}
}
小知识

通过 .Constraint<TEntity,TDbContextLocator> 方法可以将仓储约束为特定仓储,如只读仓储,可读可写仓储,只新增仓储等。

9.12.5 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/dbcontext/index.html b/docs/docs/dbcontext/index.html index ecbcd08fa88..d402b0ecee8 100644 --- a/docs/docs/dbcontext/index.html +++ b/docs/docs/dbcontext/index.html @@ -6,7 +6,7 @@ 9.1 数据库上下文 | Fur - + @@ -20,24 +20,24 @@ - +

9.1 数据库上下文

9.1.1 数据库上下文

简单来说,数据库上下文是负责和数据库交互的对象,提供程序对数据库存取提供了大量的方法。

Fur 框架中,默认集成了微软亲儿子:EntityFramework Core ,也就是通常数据库上下文指的是 DbContext 类或它的实现类。

9.1.2 AppDbContext

在我们实际项目开发过程中,使用 EFCore 提供的 DbContext 操作对象操作数据库有些繁琐和复杂,且默认不具备读写分离、多库等操作功能。

所以,Fur 框架提供了 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 能够得到 Fur 框架更多的功能支持

9.1.4 如何定义数据库上下文

Fur 框架中了,提供了两种 AppDbContext 定义方式:

  • AppDbContext<TDbContext> 操作默认数据库
  • AppDbContext<TDbContext, TDbContextLocator> 操作 N 个数据库

其中 AppDbContext<TDbContext> 默认继承自 AppDbContext<TDbContext, TDbContextLocator>

下面是数据库上下文创建的多个例子:

9.1.4.1 创建默认数据库上下文

using Fur.DatabaseAccessor;
using Microsoft.EntityFrameworkCore;
namespace Fur.EntityFramework.Core
{
[AppDbContext("连接字符串或appsetting.json 键")]
public class FurDbContext : AppDbContext<FurDbContext> // 继承 AppDbContext<> 类
{
/// <summary>
/// 继承父类构造函数
/// </summary>
/// <param name="options"></param>
public FurDbContext(DbContextOptions<FurDbContext> options) : base(options)
{
}
}
}

9.1.4.2 创建其他数据库上下文

using Fur.DatabaseAccessor;
using Microsoft.EntityFrameworkCore;
namespace Fur.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)
{
}
}
}
特别注意

所有数据库上下文都应该在 Fur.EntityFramework.Core 项目中创建。关于 TDbContextLocator 将在下一章节 《9.2 数据库上下文定位器》阐述。

9.1.5 配置连接字符串

Fur 框架提供多种数据库连接字符串配置方式:

  • Startup 中添加服务:AddSqlServerPool<TDbContext>("连接字符串") 方式
  • 使用 [AppDbContext("连接字符串/Key")] 特性方式(只在 AppDbContext 实现类有效推荐
  • 通过重写 OnConfiguring(DbContextOptionsBuilder optionsBuilder) 配置

9.1.5.1 Startup 方式配置

Fur\framework\Fur.EntityFramework.Core\FurEntityFrameworkCoreStartup.cs
using Fur.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
-
namespace Fur.EntityFramework.Core
{
[Startup(600)]
public sealed class FurEntityFrameworkCoreStartup : AppStartup
{
public void ConfigureServices(IServiceCollection services)
{
// 配置数据库上下文,支持N个数据库
services.AddDatabaseAccessor(options =>
{
// 配置默认数据库
options.AddDbPool<FurDbContext>(DbProvider.SqlServer, "连接字符串");
+
namespace Fur.EntityFramework.Core
{
[AppStartup(600)]
public sealed class FurEntityFrameworkCoreStartup : AppStartup
{
public void ConfigureServices(IServiceCollection services)
{
// 配置数据库上下文,支持N个数据库
services.AddDatabaseAccessor(options =>
{
// 配置默认数据库
options.AddDbPool<FurDbContext>(DbProvider.SqlServer, "连接字符串");
// 配置多个数据库,多个数据库必须指定数据库上下文定位器
options.AddDbPool<SqliteDbContext, SqliteDbContextLocaotr>(DbProvider.Sqlite, "连接字符串");
});
}
}
}

9.1.5.2 [AppDbContext] 方式配置

using Fur.DatabaseAccessor;
using Microsoft.EntityFrameworkCore;
namespace Fur.EntityFramework.Core
{
[AppDbContext("DbConnectionString")] // 支持 `appsetting.json` 名或 连接字符串
public class FurDbContext : AppDbContext<FurDbContext>
{
/// <summary>
/// 继承父类构造函数
/// </summary>
/// <param name="options"></param>
public FurDbContext(DbContextOptions<FurDbContext> options) : base(options)
{
}
}
}
小提示

Fur 推荐使用此方式配置数据库连接字符串。

[AppDbContext] 内置属性:

  • ConnectionString:数据库连接字符串,或配置文件中的路径(支持自定义配置查找),或 appsetting.jsonConnectionStrings 配置字符串
  • TablePrefix:当前数据库上下文表统一前缀
  • TableSuffix:当前数据库上下文表统一后缀

9.1.5.3 OnConfiguring 方式配置

using Fur.DatabaseAccessor;
using Microsoft.EntityFrameworkCore;
namespace Fur.EntityFramework.Core
{
public class FurDbContext : AppDbContext<FurDbContext>
{
/// <summary>
/// 继承父类构造函数
/// </summary>
/// <param name="options"></param>
public FurDbContext(DbContextOptions<FurDbContext> options) : base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
-
optionsBuilder.UseSqlServer("数据库连接字符串");
}
}
}
特别注意

这三种方式可以同时使用,但是有优先级:[AppDbContext] -> Startup -> OnConfiguring(低到高)

也就是 OnConfiguring 配置会覆盖 Startup 配置,Startup 配置会覆盖 [AppDbContext] 配置所配置的连接字符串。

9.1.6 数据库上下文定义位置

特别注意

Fur 框架中,数据库上下文需定义在 Fur.EntityFramework.Core 中,且每一个数据库上下文都必须拥有唯一的 DbContextLocator 定位器

9.1.7 数据库上下文注册

数据库上下文配置好数据库连接字符串后,需要注册改数据库上下文,并指定数据库类型,如:

Fur\framework\Fur.EntityFramework.Core\FurEntityFrameworkCoreStartup.cs
using Fur.DatabaseAccessor;
using Microsoft.Extensions.DependencyInjection;
-
namespace Fur.EntityFramework.Core
{
[Startup(600)]
public sealed class FurEntityFrameworkCoreStartup : AppStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddDatabaseAccessor(options =>
{
options.AddDbPool<FurDbContext>(DbProvider.Sqlite);
});
}
}
}

如果有多个数据库操作,那么从第二个起,就需要绑定数据库上下文定位器,如:

options.AddDbPool<FurDbContext>(DbProvider.Sqlite); // 第一个数据库
+
optionsBuilder.UseSqlServer("数据库连接字符串");
}
}
}
特别注意

这三种方式可以同时使用,但是有优先级:[AppDbContext] -> Startup -> OnConfiguring(低到高)

也就是 OnConfiguring 配置会覆盖 Startup 配置,Startup 配置会覆盖 [AppDbContext] 配置所配置的连接字符串。

9.1.6 数据库上下文定义位置

特别注意

Fur 框架中,数据库上下文需定义在 Fur.EntityFramework.Core 中,且每一个数据库上下文都必须拥有唯一的 DbContextLocator 定位器

9.1.7 数据库上下文注册

数据库上下文配置好数据库连接字符串后,需要注册该数据库上下文,并指定数据库类型,如:

Fur\framework\Fur.EntityFramework.Core\FurEntityFrameworkCoreStartup.cs
using Fur.DatabaseAccessor;
using Microsoft.Extensions.DependencyInjection;
+
namespace Fur.EntityFramework.Core
{
[AppStartup(600)]
public sealed class FurEntityFrameworkCoreStartup : AppStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddDatabaseAccessor(options =>
{
options.AddDbPool<FurDbContext>(DbProvider.Sqlite);
});
}
}
}

如果有多个数据库操作,那么从第二个起,就需要绑定数据库上下文定位器,如:

options.AddDbPool<FurDbContext>(DbProvider.Sqlite); // 第一个数据库
options.AddDbPool<SecondDbContext, SecondDbContextDbContextLocator>(DbProvider.SqlServer); // 第二个数据库
options.AddDbPool<ThirdDbContext, ThirdDbContextDbContextLocator>(DbProvider.SqlServer); // 第三个数据库

9.1.8 动态数据库上下文对象

Fur 框架中,数据库上下文是定义在 Fur.EntityFramework.Core 项目层,并且该层不被 Fur.ApplicationFur.Core 等层引用。

所以就不能直接在 Fur.Application 项目层直接使用 Fur.EntityFramework.Core 定义的数据库上下文。

Fur 为了解决这个问题,提供了两种方式处理:

  • respository.DbContext :当前数据库上下文对象,返回是 DbContext 抽象类型
  • respository.DynamicDbContext:当前数据库上下文对象,返回的是 dynamic 类型

如果你只是想使用 DbContext 的功能,直接使用 respository.DbContext 即可,如:

respository.DbContext.SaveChanges();

如果你想能够获取具体的数据库上下文类型,如 MyDbContext,那么使用 respository.DynamicDbContext 就可以获取到具体的 MyDbContext 类型。如:

var persons = respository.DynamicDbContext.Persons.Find(1);
var users = respository.DynamicDbContext.Users;

这样就可以直接操作 MyDbContext 定义的属性和方法了。

9.1.9 反馈与建议

与我们交流

给 Fur 提 Issue


了解更多

想了解更多 数据库上下文 知识可查阅 EF Core - 配置 DbContext 章节。

- + @@ -51,6 +51,6 @@ - + \ No newline at end of file diff --git a/docs/docs/dependency-injection/index.html b/docs/docs/dependency-injection/index.html index 76b5e25e3f5..b5fb87a2aa9 100644 --- a/docs/docs/dependency-injection/index.html +++ b/docs/docs/dependency-injection/index.html @@ -6,7 +6,7 @@ 11. 依赖注入/控制反转 | Fur - + @@ -26,7 +26,7 @@
- + diff --git a/docs/docs/deploy/index.html b/docs/docs/deploy/index.html index 05e7f4e4682..60a7dc47e4f 100644 --- a/docs/docs/deploy/index.html +++ b/docs/docs/deploy/index.html @@ -6,7 +6,7 @@ 25. 托管部署 | Fur - + @@ -26,7 +26,7 @@
- + diff --git a/docs/docs/devops/index.html b/docs/docs/devops/index.html index efeee23b1d0..ec4e40f9866 100644 --- a/docs/docs/devops/index.html +++ b/docs/docs/devops/index.html @@ -6,7 +6,7 @@ 26. 持续部署集成 | Fur - + @@ -26,7 +26,7 @@
- + diff --git a/docs/docs/dynamic-api-controller/index.html b/docs/docs/dynamic-api-controller/index.html index 1a159e9f0ee..dfbc2e9c72f 100644 --- a/docs/docs/dynamic-api-controller/index.html +++ b/docs/docs/dynamic-api-controller/index.html @@ -6,7 +6,7 @@ 5. 动态 WebAPI | Fur - + @@ -75,7 +75,7 @@
namespace Fur.Web.Entry.Controllers
{
public class MvcController : ControllerBase
{
public string Get()
{
return nameof(Fur);
}
}
}
注意事项

启用该配置后,如果 Mvc 控制器 没有任何 [Route] 特性,但是贴了 [ApiController] 特性将会报错。原因是 [ApiController] 特性内部做了路由特性检测。所以建议使用 [ApiDataValidation] 代替。

查看 ASP.NET Core - ApiBehaviorApplicationModelProvider 源码

5.11 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/entity/index.html b/docs/docs/entity/index.html index 2fec3c4aa1d..5dc5b036ab2 100644 --- a/docs/docs/entity/index.html +++ b/docs/docs/entity/index.html @@ -6,7 +6,7 @@ 9.3 数据库实体 | Fur - + @@ -39,7 +39,7 @@
// 配置数据库实体
public void Configure(EntityTypeBuilder<User> entityBuilder, DbContext dbContext, Type dbContextLocator)
{
entityBuilder.HasKey(u => u.Id);
entityBuilder.HasIndex(u => u.Name);
}
}
}

9.3.3.2 在任何实例类中配置

using Fur.DatabaseAccessor;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using System;
namespace Fur.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 数据库实体。

9.3.4 数据库实体配置说明

Fur 框架会自动扫描所有继承 IEntity 接口的类进行 DbSet<TEntity> 注册,也就是实现自动配置 DbContextOnModelCreating

如果需要跳过自动注册,只需要贴 [NonAutomatic][NonBeScan] 特性即可。一旦贴了次特性,那么就需要手动配置 DbContextOnModelCreating

9.3.5 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/event-bus/index.html b/docs/docs/event-bus/index.html index d03fffe8817..63470850415 100644 --- a/docs/docs/event-bus/index.html +++ b/docs/docs/event-bus/index.html @@ -6,7 +6,7 @@ 18. 事件总线 | Fur - + @@ -26,7 +26,7 @@
- + diff --git a/docs/docs/friendly-exception/index.html b/docs/docs/friendly-exception/index.html index 744e124a0b4..953bf0f62e6 100644 --- a/docs/docs/friendly-exception/index.html +++ b/docs/docs/friendly-exception/index.html @@ -6,7 +6,7 @@ 7. 友好异常处理 | Fur - + @@ -59,7 +59,7 @@
namespace Fur.Application
{
public class FurAppService : IDynamicApiController
{
[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 异常模型提供器

文档整理中...

7.14 Fur 内置异常

  • EFCoreErrorCodesEF Core 操作异常
    • DataNotFound:未找到数据
    • KeyNotSet:没有设置主键

7.15 反馈与建议

与我们交流

给 Fur 提 Issue

- + diff --git a/docs/docs/get-start/index.html b/docs/docs/get-start/index.html index 48514b67928..01b1c4725d4 100644 --- a/docs/docs/get-start/index.html +++ b/docs/docs/get-start/index.html @@ -6,7 +6,7 @@ 2. 一分钟入门 | Fur - + @@ -20,7 +20,7 @@ - +
@@ -30,8 +30,8 @@
/// <summary>
/// 姓名
/// </summary>
[MaxLength(32)]
public string Name { get; set; }
/// <summary>
/// 年龄
/// </summary>
public int Age { get; set; }
/// <summary>
/// 住址
/// </summary>
public string Address { get; set; }
}
}

2.2.2 创建数据库上下文

Fur.EntityFramework.Core 中添加 FurDbContext 数据库上下文,代码如下:

using Fur.DatabaseAccessor;
using Microsoft.EntityFrameworkCore;
-
namespace Fur.EntityFramework.Core
{
[AppDbContext("DbConnectionString")] // 配置连接字符串
public class FurDbContext : AppDbContext<FurDbContext> // 继承 AppDbContext<> 类
{
/// <summary>
/// 继承父类构造函数
/// </summary>
/// <param name="options"></param>
public FurDbContext(DbContextOptions<FurDbContext> options) : base(options)
{
}
}
}

2.2.3 配置数据库连接字符串

Fur.EntityFramework.Coredbsettings.json 中配置数据库连接字符串,代码如下:

Fur\framework\Fur.EntityFramework.Core\dbsettings.json
{
"ConnectionStrings": {
"DbConnectionString": "Server=localhost;Database=Fur;User=sa;Password=000000;MultipleActiveResultSets=True;",
"Sqlite3ConnectionString": "Data Source=./Fur.db"
}
}

2.2.4 配置数据库上下文

Fur.EntityFramework.CoreFurEntityFrameworkCoreStartup 中配置数据库上下文,代码如下:

Fur\framework\Fur.EntityFramework.Core\FurEntityFrameworkCoreStartup.cs
using Fur.DatabaseAccessor;
using Microsoft.Extensions.DependencyInjection;
-
namespace Fur.EntityFramework.Core
{
[Startup(600)]
public sealed class FurEntityFrameworkCoreStartup : AppStartup
{
public void ConfigureServices(IServiceCollection services)
{
// 配置数据库上下文,支持N个数据库
services.AddDatabaseAccessor(options =>
{
options.AddDbPool<FurDbContext>(DbProvider.Sqlite);
});
}
}
}
特别说明

Fur 演示示例中,默认已经在 Fur.EntityFramework.Core 层安装了 Microsoft.EntityFrameworkCore.Sqlite 包。

如果你需要安装对应的数据库版本,可以查阅 【9.18 多数据库操作】 章节。

2.2.5 通过命令创建数据库表

打开 程序包管理控制台,如下图所示:

选择 默认项目为Fur.Database.Migrations,如下图所示:

输入以下命令

Add-Migration v0.0.1

提交到数据库更改

Update-Database

2.3 增删查改分页例子

using Fur.Core;
using Fur.DatabaseAccessor;
using Fur.DynamicApiController;
using Mapster;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Threading.Tasks;
+
namespace Fur.EntityFramework.Core
{
[AppDbContext("Data Source=./Fur.db")] // 配置连接字符串
public class FurDbContext : AppDbContext<FurDbContext> // 继承 AppDbContext<> 类
{
/// <summary>
/// 继承父类构造函数
/// </summary>
/// <param name="options"></param>
public FurDbContext(DbContextOptions<FurDbContext> options) : base(options)
{
}
}
}

2.2.3 配置数据库上下文

Fur.EntityFramework.CoreFurEntityFrameworkCoreStartup 中配置数据库上下文,代码如下:

Fur\framework\Fur.EntityFramework.Core\FurEntityFrameworkCoreStartup.cs
using Fur.DatabaseAccessor;
using Microsoft.Extensions.DependencyInjection;
+
namespace Fur.EntityFramework.Core
{
[AppStartup(600)]
public sealed class FurEntityFrameworkCoreStartup : AppStartup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddDatabaseAccessor(options =>
{
options.AddDbPool<FurDbContext>(DbProvider.Sqlite);
});
}
}
}
特别说明

Fur 演示示例中,默认已经在 Fur.EntityFramework.Core 层安装了 Microsoft.EntityFrameworkCore.Sqlite 包。

如果你需要安装对应的数据库版本,可以查阅 【9.18 多数据库操作】 章节。

2.2.4 通过命令创建数据库表

打开 程序包管理控制台,如下图所示:

选择 默认项目为Fur.Database.Migrations,如下图所示:

输入以下命令

Add-Migration v0.0.1

提交到数据库更改

Update-Database

2.3 增删查改分页例子

using Fur.Core;
using Fur.DatabaseAccessor;
using Fur.DynamicApiController;
using Mapster;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Fur.Application
{
[DynamicApiController] // 这里使用特性方式
public class FurService /*: IDynamicApiController*/ // 也可以使用接口方式
{
// 初始化仓储
private readonly IRepository<Person> _personRepository;
public FurService(IRepository<Person> personRepository)
{
_personRepository = personRepository;
}
/// <summary>
/// 新增一条
/// </summary>
public async Task<int> Insert(PersonDto personDto)
{
// 如果不需要返回自增Id,使用 InsertAsync即可
var newEntity = await _personRepository.InsertNowAsync(personDto.Adapt<Person>());
return newEntity.Entity.Id;
// 还可以直接操作
// await personDto.Adapt<Person>().InsertNowAsync();
}
@@ -43,9 +43,9 @@
/// <summary>
/// 分页查询
/// </summary>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
public async Task<PagedList<PersonDto>> GetAllByPage(int pageIndex = 1, int pageSize = 10)
{
var pageResult = await _personRepository.AsQueryable().ToPagedListAsync(pageIndex, pageSize);
return pageResult.Adapt<PagedList<PersonDto>>();
}
}
}

附上 PersonDto

using System.ComponentModel.DataAnnotations;
namespace Fur.Application
{
public class PersonDto
{
/// <summary>
/// Id
/// </summary>
public int? Id { get; set; }
/// <summary>
/// 姓名
/// </summary>
[StringLength(32, MinimumLength = 2)]
public string Name { get; set; }
-
/// <summary>
/// 年龄
/// </summary>
public int Age { get; set; }
}
}

说好一分钟入门,你们用了多长时间。😁

+
/// <summary>
/// 年龄
/// </summary>
public int Age { get; set; }
}
}

说好一分钟入门,你们用了多长时间。😁

- + @@ -59,6 +59,6 @@ - + \ No newline at end of file diff --git a/docs/docs/grpc/index.html b/docs/docs/grpc/index.html index 5f61f7d2f83..8575201163a 100644 --- a/docs/docs/grpc/index.html +++ b/docs/docs/grpc/index.html @@ -6,7 +6,7 @@ 24. Grpc 服务 | Fur - + @@ -26,7 +26,7 @@
- + diff --git a/docs/docs/index.html b/docs/docs/index.html index 134939d4ae7..f88360dac31 100644 --- a/docs/docs/index.html +++ b/docs/docs/index.html @@ -6,7 +6,7 @@ 1.1 介绍 | Fur - + @@ -26,7 +26,7 @@

1.1 介绍

star fork GitHub stars GitHub forks GitHub license

Fur.NET 5 平台下极易入门、极速开发的 Web 应用框架。

🍕 名字的由来

故事是这样子的:

起初,想开发一个极易入门、极易维护的框架,开发理念为:一切从简,只为了更懒

所以自然而然想到了:Lazier,也就是 更懒 的意思。但是 更懒更烂 读音相近且中文名没有特色,对此换名问题我苦恼了好几天。

刚好有一次我在博客园中帮一个博友解答问题,解决后博友赞扬我对 .NET Core 颇有了解,我就顺嘴回答了一句:“略懂皮毛”

就这时,脑瓜子灵机一动,干脆起名为:“皮毛”?英文单词 Fur [fɜː(r)]”,单词又短而且中文读音既俗气又顺口。😄😎

所以,Fur 就诞生了。

之后就有了 “小僧不才,略懂皮毛(Fur)。” 广告语 和 chinadot.net 域名。

🍔 关于 LOGO

Fur LOGO 设计由 F U R 三个单词组成:

我相信很多人看到 Fur 的 LOGO 时都会问:“为什么选择奶牛?”,因为 那些年吹过的牛逼都实现了 🐮

之所以选择 奶牛 是因为 具有脚踏实地,任劳任怨的做事风格,同时 奶牛 意味着丰富的营养价值,正如 Fur 所能带给你的。

🍟 文档地址

https://chinadot.net

🌭 开源地址

🍿 Docker 镜像

docker run --name fur -p 5000:80 monksoul/fur:v1.0.0-2020.10.07

🥞 架构设计

正在整理中...

🥝 功能模块

🥐 框架依赖

Fur 为了追求极速入门,极致性能,尽可能的不使用或减少第三方依赖。目前 Fur 仅集成了以下三个依赖:

麻雀虽小五脏俱全。Fur 即使只集成了这三个依赖,但是主流的 依赖注入/控制反转AOP 面向切面编程,事件总线数据验证数据库操作 等等一个都不少。

🥗 环境要求

  • Visual Studio 2019 Preview 16.8 +
  • .NET 5 SDK +
  • .Net Standard 2.1 +

🥪 支持平台

  • 运行环境
    • Windows
    • Linux
    • MacOS
    • Docker/K8S/K3S/Rancher
  • 数据库
    • SqlServer
    • Sqlite
    • Azure Cosmos
    • MySql
    • PostgreSQL
    • InMemoryDatabase
    • Oracle
    • Firebird
    • 达梦数据库
  • 应用部署
    • Kestrel
    • Nginx
    • Jexus
    • IIS
    • Apache
    • PM2
    • Supervisor
    • 单文件
    • 容器(Docker/K8S/K3S/Rancher)

🍖 关于性能

Fur 目前采用 Visual Studio 2019 Preview 16.8 自带性能测试和 JMeter 进行测试,由于篇幅有限,只贴部分测试图,测试结果如下:


🍚 关于作者

一个拥有 12 年开发经验 .NETer。喜欢分享,喜欢新技术,在互联网多个技术领域皆有涉猎。

🍤 项目成员

🎈 欢迎更多的开发者加入 Fur 大家庭。

🍝 谁在使用

  • 百签科技(广东)有限公司
  • 码为科技(广州)有限公司
  • 广州启顺国际货运代理有限公司
  • 森丰供应链服务(广州)有限公司
  • 中山赢友网络科技有限公司
  • 中山模思软件科技有限公司
  • 珠海市恒泰新软件有限责任公司
  • 珠海思诺锐创软件有限公司
  • 深圳市易胜科技有限公司
  • 重庆虫儿飞科技有限公司
  • 重庆林木森科技有限公司

如果您的项目使用到 Fur 开发,可以告诉我们。

🍻 贡献代码

Fur 遵循 Apache-2.0 开源协议,欢迎大家提交 PRIssue

如果要为项目做出贡献,请查看贡献指南。

🍍 捐赠列表

注:排序按捐赠顺序书写

捐赠人昵称捐赠金额(元)附语
🤴 爱吃油麦菜100感谢您的开源项目!
👳‍♂️ 麦壳饼200感谢您的开源项目!
👨 Sun100感谢您的开源项目!
👶 d61761720感谢您的开源项目!
👦 Diqiguoji00816.66见贤思齐
👲 nodyang100感谢您的开源项目!
👳‍♀️ mictxd100吹过的牛都实现。
🧓 欧流全10希望将来超越 Spring
👨‍⚕️ lionkon10...看了框架感觉拿来学习是很不错的...

非常感谢您们的支持,正是因为您们,中国开源才可以越走越远,Fur 越走越远。

🥔 QQ 交流群

🧆 友情链接

👉 Fur 👉 SqlSugar 👉 Layx 👉 t-io

- + diff --git a/docs/docs/job/index.html b/docs/docs/job/index.html index 6377128efc6..2eb964098c2 100644 --- a/docs/docs/job/index.html +++ b/docs/docs/job/index.html @@ -6,7 +6,7 @@ 22. 任务调度 | Fur - + @@ -26,7 +26,7 @@
- + diff --git a/docs/docs/local-language/index.html b/docs/docs/local-language/index.html index c1f31422b8b..2b5417c70c5 100644 --- a/docs/docs/local-language/index.html +++ b/docs/docs/local-language/index.html @@ -6,7 +6,7 @@ 16. 多语言处理 | Fur - + @@ -26,7 +26,7 @@
- + diff --git a/docs/docs/logging/index.html b/docs/docs/logging/index.html index faa176df3bd..708d797411c 100644 --- a/docs/docs/logging/index.html +++ b/docs/docs/logging/index.html @@ -6,7 +6,7 @@ 19. 日志记录 | Fur - + @@ -26,7 +26,7 @@
- + diff --git a/docs/docs/object-mapper/index.html b/docs/docs/object-mapper/index.html index a615fc09b3d..7cba2fbebad 100644 --- a/docs/docs/object-mapper/index.html +++ b/docs/docs/object-mapper/index.html @@ -6,7 +6,7 @@ 12. 对象数据映射 | Fur - + @@ -26,7 +26,7 @@
- + diff --git a/docs/docs/options/index.html b/docs/docs/options/index.html index 01b8d88c496..3eb8efceb72 100644 --- a/docs/docs/options/index.html +++ b/docs/docs/options/index.html @@ -6,7 +6,7 @@ 4.2 选项 | Fur - + @@ -41,7 +41,7 @@
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.9 选项的优缺点

优点

  • 强类型配置
  • 提供多种读取方式
  • 支持热加载
  • 支持设置默认值/后期配置
  • 支持在运行环境中动态配置
  • 支持验证配置有效性
  • 支持更改通知
  • 支持命名选项

缺点

  • 需要定义对应类型
  • 需要在启动时注册

4.2.10 反馈与建议

与我们交流

给 Fur 提 Issue


了解更多

想了解更多 选项 知识可查阅 ASP.NET Core - 选项 章节。

- + diff --git a/docs/docs/performance/index.html b/docs/docs/performance/index.html index 906e6d255ba..9d2521373b1 100644 --- a/docs/docs/performance/index.html +++ b/docs/docs/performance/index.html @@ -6,7 +6,7 @@ 27.2 性能测试 | Fur - + @@ -26,7 +26,7 @@
- + diff --git a/docs/docs/process-service/index.html b/docs/docs/process-service/index.html index 272a2639f02..5b518777524 100644 --- a/docs/docs/process-service/index.html +++ b/docs/docs/process-service/index.html @@ -6,7 +6,7 @@ 21. 进程服务 | Fur - + @@ -26,7 +26,7 @@
- + diff --git a/docs/docs/saas/index.html b/docs/docs/saas/index.html index a37f0a72a8a..806f7ac560d 100644 --- a/docs/docs/saas/index.html +++ b/docs/docs/saas/index.html @@ -6,7 +6,7 @@ 10. SaaS 多租户 | Fur - + @@ -20,7 +20,7 @@ - +
@@ -32,7 +32,7 @@ 三种方案比较,第三种方案的维护和购置成本最低,允许每个数据库支持的租户数量最多。

  • 缺点: 隔离级别最低,安全性最低,需要在设计开发时加大对安全的开发量; 数据备份和恢复最困难,需要逐表逐条备份和还原。

  • 10.4 多租户使用方案

    Fur 框架支持以上三种多租户实现方案,使用简单且容易维护。下面分别使用三种不同方式演示多租户方案用法。

    10.5 基于 TenantId 的方式

    此方式在中小型企业系统中最为常用,维护成本低,购置成本低。

    10.5.1 创建租户数据库上下文

    Fur.EntityFramework.Core\DbContexts\MultiTenantDbContext.cs
    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    namespace Fur.EntityFramework.Core
    {
    [AppDbContext("Sqlite3ConnectionString")]
    public class MultiTenantDbContext : AppDbContext<MultiTenantDbContext, MultiTenantDbContextLocator>
    {
    public MultiTenantDbContext(DbContextOptions<MultiTenantDbContext> options) : base(options)
    {
    }
    }
    }
    特别注意

    多租户操作建议单独一个数据库上下文,而且需指定 MultiTenantDbContextLocator 数据库上下文定位器。

    10.5.2 注册多租户数据库上下文

    using Fur.DatabaseAccessor;
    using Microsoft.Extensions.DependencyInjection;
    -
    namespace Fur.EntityFramework.Core
    {
    [Startup(600)]
    public sealed class FurEntityFrameworkCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddDatabaseAccessor(options =>
    {
    options.AddDbPool<FurDbContext>(DbProvider.Sqlite);
    options.AddDbPool<MultiTenantDbContext, MultiTenantDbContextLocator>(DbProvider.Sqlite);
    });
    }
    }
    }

    10.5.3 添加 Tenant 种子数据

    Fur.EntityFramework.Core\SeedDatas\TenantSeedData.cs
    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    using System;
    using System.Collections.Generic;
    +
    namespace Fur.EntityFramework.Core
    {
    [AppStartup(600)]
    public sealed class FurEntityFrameworkCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddDatabaseAccessor(options =>
    {
    options.AddDbPool<FurDbContext>(DbProvider.Sqlite);
    options.AddDbPool<MultiTenantDbContext, MultiTenantDbContextLocator>(DbProvider.Sqlite);
    });
    }
    }
    }

    10.5.3 添加 Tenant 种子数据

    Fur.EntityFramework.Core\SeedDatas\TenantSeedData.cs
    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    using System;
    using System.Collections.Generic;
    namespace Fur.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 无需配置种子数据。

    10.5.4 根据模型创建 Tenant

    Add-Migration add_tenant_table -Context MultiTenantDbContext
    Update-Database -Context MultiTenantDbContext

    10.5.5 实现 IMultiTenantOnTable 接口

    在需要多租户的数据库上下文中实现 IMultiTenantOnTable 接口,如:

    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    using System;
    namespace Fur.EntityFramework.Core
    {
    [AppDbContext("Sqlite3ConnectionString")]
    public class FurDbContext : AppDbContext<FurDbContext>, IMultiTenantOnTable, IModelBuilderFilter
    {
    public FurDbContext(DbContextOptions<FurDbContext> options) : base(options)
    {
    }
    public Guid? GetTenantId()
    {
    return base.Tenant.TenantId;
    }
    }
    }

    GetTenantId() 方法中,首先获取请求的 主机地址,然后根据主机地址查询对应的租户 TenantIdId,避免多次查询数据库,这里使用了 IMemoryCache 内存缓存。

    10.5.6 实现 IModelBuilderFilter 接口

    IModelBuilderFilter 接口是全局查询过滤器实现接口,所以我们需要配置实体 TenantId 过滤器

    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.EntityFrameworkCore.Metadata.Builders;
    using System;
    @@ -46,7 +46,7 @@
    // 获取所有新增和更新的实体
    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 = base.TenantId;
    break;
    // 排除租户Id
    case EntityState.Modified:
    entity.Property(nameof(Entity.TenantId)).IsModified = false;
    break;
    }
    }
    }
    }
    }

    10.6 基于 Database 的方式

    此方式在中大型企业系统中最为常用,一个租户(客户)一个独立的数据库。

    10.6.1 创建租户数据库上下文

    Fur.EntityFramework.Core\DbContexts\MultiTenantDbContext.cs
    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    namespace Fur.EntityFramework.Core
    {
    [AppDbContext("Sqlite3ConnectionString")]
    public class MultiTenantDbContext : AppDbContext<MultiTenantDbContext, MultiTenantDbContextLocator>
    {
    public MultiTenantDbContext(DbContextOptions<MultiTenantDbContext> options) : base(options)
    {
    }
    }
    }
    特别注意

    多租户操作建议单独一个数据库上下文,而且需指定 MultiTenantDbContextLocator 数据库上下文定位器。

    10.6.2 注册多租户数据库上下文

    using Fur.DatabaseAccessor;
    using Microsoft.Extensions.DependencyInjection;
    -
    namespace Fur.EntityFramework.Core
    {
    [Startup(600)]
    public sealed class FurEntityFrameworkCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddDatabaseAccessor(options =>
    {
    options.AddDb<FurDbContext>(DbProvider.Sqlite);
    options.AddDbPool<MultiTenantDbContext, MultiTenantDbContextLocator>(DbProvider.Sqlite);
    });
    }
    }
    }
    特别注意

    需要 Database 多租户方案的数据库上下文需要采用 AddDb 注册,而不是 AddDbPool。原因是 AddDbPool 方式注册后续不支持 OnConfiguring 重写!!!

    10.6.3 添加 Tenant 种子数据

    Fur.EntityFramework.Core\SeedDatas\TenantSeedData.cs
    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    using System;
    using System.Collections.Generic;
    +
    namespace Fur.EntityFramework.Core
    {
    [AppStartup(600)]
    public sealed class FurEntityFrameworkCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddDatabaseAccessor(options =>
    {
    options.AddDb<FurDbContext>(DbProvider.Sqlite);
    options.AddDbPool<MultiTenantDbContext, MultiTenantDbContextLocator>(DbProvider.Sqlite);
    });
    }
    }
    }
    特别注意

    需要 Database 多租户方案的数据库上下文需要采用 AddDb 注册,而不是 AddDbPool。原因是 AddDbPool 方式注册后续不支持 OnConfiguring 重写!!!

    10.6.3 添加 Tenant 种子数据

    Fur.EntityFramework.Core\SeedDatas\TenantSeedData.cs
    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    using System;
    using System.Collections.Generic;
    namespace Fur.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=./Fur.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 无需配置种子数据。

    10.6.4 根据模型创建 Tenant

    Add-Migration add_tenant_table -Context MultiTenantDbContext
    Update-Database -Context MultiTenantDbContext

    10.6.5 实现 IMultiTenantOnDatabase 接口

    在需要多租户的数据库上下文中实现 IMultiTenantOnDatabase 接口,如:

    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    namespace Fur.EntityFramework.Core
    {
    public class FurDbContext : AppDbContext<FurDbContext>, IMultiTenantOnDatabase
    {
    public FurDbContext(DbContextOptions<FurDbContext> options) : base(options)
    {
    }
    public string GetDatabaseConnectionString()
    {
    return base.Tenant.ConnectionString;
    }
    }
    }

    10.6.6 重写 OnConfiguring 方法

    在需要多租户的数据库上下文中重写 OnConfiguring 方法并配置连接字符串:

    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    @@ -55,12 +55,12 @@
    base.OnConfiguring(optionsBuilder);
    }
    public string GetDatabaseConnectionString()
    {
    return base.Tenant.ConnectionString;
    }
    }
    }

    10.7 基于 Schema 的方式

    此方式在中小型企业系统中也不少见,一个租户(客户)共享数据库且不同 Schema

    10.7.1 创建租户数据库上下文

    Fur.EntityFramework.Core\DbContexts\MultiTenantDbContext.cs
    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    namespace Fur.EntityFramework.Core
    {
    [AppDbContext("Sqlite3ConnectionString")]
    public class MultiTenantDbContext : AppDbContext<MultiTenantDbContext, MultiTenantDbContextLocator>
    {
    public MultiTenantDbContext(DbContextOptions<MultiTenantDbContext> options) : base(options)
    {
    }
    }
    }
    特别注意

    多租户操作建议单独一个数据库上下文,而且需指定 MultiTenantDbContextLocator 数据库上下文定位器。

    10.7.2 注册多租户数据库上下文

    using Fur.DatabaseAccessor;
    using Microsoft.Extensions.DependencyInjection;
    -
    namespace Fur.EntityFramework.Core
    {
    [Startup(600)]
    public sealed class FurEntityFrameworkCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddDatabaseAccessor(options =>
    {
    options.AddDbPool<FurDbContext>(DbProvider.Sqlite);
    options.AddDbPool<MultiTenantDbContext, MultiTenantDbContextLocator>(DbProvider.Sqlite);
    });
    }
    }
    }

    10.7.3 添加 Tenant 种子数据

    Fur.EntityFramework.Core\SeedDatas\TenantSeedData.cs
    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    using System;
    using System.Collections.Generic;
    +
    namespace Fur.EntityFramework.Core
    {
    [AppStartup(600)]
    public sealed class FurEntityFrameworkCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddDatabaseAccessor(options =>
    {
    options.AddDbPool<FurDbContext>(DbProvider.Sqlite);
    options.AddDbPool<MultiTenantDbContext, MultiTenantDbContextLocator>(DbProvider.Sqlite);
    });
    }
    }
    }

    10.7.3 添加 Tenant 种子数据

    Fur.EntityFramework.Core\SeedDatas\TenantSeedData.cs
    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    using System;
    using System.Collections.Generic;
    namespace Fur.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="fur" // Schema
    }
    };
    }
    }
    }
    特别说明

    该步骤只在 Code First 方式执行,Database First 无需配置种子数据。

    10.7.4 根据模型创建 Tenant

    Add-Migration add_tenant_table -Context MultiTenantDbContext
    Update-Database -Context MultiTenantDbContext

    10.7.5 实现 IMultiTenantOnSchema 接口

    在需要多租户的数据库上下文中实现 IMultiTenantOnSchema 接口,如:

    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    namespace Fur.EntityFramework.Core
    {
    [AppDbContext("Sqlite3ConnectionString")]
    public class FurDbContext : AppDbContext<FurDbContext>, IMultiTenantOnSchema
    {
    public FurDbContext(DbContextOptions<FurDbContext> options) : base(options)
    {
    }
    public string GetSchemaName()
    {
    return base.Tenant.Schema;
    }
    }
    }

    10.7.6 关于 Code First 数据迁移

    基于 Schema 方式比较特别,生成数据迁移的时候没办法获取租户信息,所以建议分开多次迁移,如:

    public string GetSchemaName()
    {
    return base.Tenant.Schema?? "租户一Schema";
    }
    public string GetSchemaName()
    {
    return base.Tenant.Schema?? "租户二Schema";
    }

    这样就可以在迁移的时候生成多次迁移了。

    10.8 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + @@ -74,6 +74,6 @@ - + \ No newline at end of file diff --git a/docs/docs/signalr/index.html b/docs/docs/signalr/index.html index fb924d4f103..59e8f98ba97 100644 --- a/docs/docs/signalr/index.html +++ b/docs/docs/signalr/index.html @@ -6,7 +6,7 @@ 23. 即时通讯 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/docs/docs/source/index.html b/docs/docs/source/index.html index 93dda5958e0..c2a1a7ec378 100644 --- a/docs/docs/source/index.html +++ b/docs/docs/source/index.html @@ -6,7 +6,7 @@ 1.2 源码结构 | Fur - + @@ -58,7 +58,7 @@
    #prefer fields not to be prefaced with this. or Me. in Visual Basic
    dotnet_style_qualification_for_field = false:suggestion
    #prefer methods not to be prefaced with this. or Me. in Visual Basic
    dotnet_style_qualification_for_method = false:suggestion
    #prefer properties not to be prefaced with this. or Me. in Visual Basic
    dotnet_style_qualification_for_property = false:suggestion
    # Add file header
    file_header_template = -----------------------------------------------------------------------------\nFur 是 .NET 5 平台下极易入门、极速开发的 Web 应用框架。\nCopyright © 2020 Fur, Baiqian Co.,Ltd.\n\n框架名称:Fur\n框架作者:百小僧\n框架版本:1.0.0\n源码地址:Gitee:https://gitee.com/monksoul/Fur \n Github:https://github.com/monksoul/Fur \n开源协议:Apache-2.0(http://www.apache.org/licenses/LICENSE-2.0)\n-----------------------------------------------------------------------------

    1.2.4 Fur 核心层

    Fur 核心层是 Fur 框架的中心,也是 Fur 能够支撑起来的必备层。

    源码结构:

    Fur
    ├─Fur.csproj
    ├─Fur.csproj.user
    ├─FurStartup.cs
    ├─ViewEngine
    | ├─IViewEngine.cs
    | ├─ViewEngine.cs
    | ├─Templates
    | | ├─IViewEngineCompiledTemplate.cs
    | | ├─IViewEngineTemplate.cs
    | | ├─ViewEngineCompiledTemplate.cs
    | | └ViewEngineTemplate.cs
    | ├─Options
    | | └ViewEngineCompilationOptions.cs
    | ├─Models
    | | └AnonymousTypeWrapper.cs
    | ├─Exceptions
    | | ├─ViewEngineCompilationException.cs
    | | └ViewEngineException.cs
    | ├─Compilations
    | | ├─IViewEngineCompilationOptionsBuilder.cs
    | | └ViewEngineCompilationOptionsBuilder.cs
    ├─UnifyResult
    | ├─Providers
    | | ├─IUnifyResultProvider.cs
    | | └RESTfulResultProvider.cs
    | ├─Models
    | | └RESTfulResult.cs
    | ├─Filters
    | | └SuccessUnifyResultFilter.cs
    | ├─Extensions
    | | └UnifyResultServiceCollectionExtensions.cs
    ├─SpecificationDocument
    | ├─Options
    | | └SpecificationDocumentSettingsOptions.cs
    | ├─Models
    | | ├─GroupOrder.cs
    | | ├─SpecificationOpenApiInfo.cs
    | | ├─SpecificationOpenApiSecurityRequirementItem.cs
    | | └SpecificationOpenApiSecurityScheme.cs
    | ├─Extensions
    | | ├─SpecificationDocumentApplicationBuilderExtensions.cs
    | | └SpecificationDocumentServiceCollectionExtensions.cs
    | ├─Builders
    | | └SpecificationDocumentBuilder.cs
    | ├─Assets
    | | └index-mini-profiler.html
    ├─ObjectMapper
    | ├─Extensions
    | | └ObjectMapperServiceCollectionExtensions.cs
    | ├─Dependencies
    | | └IObjectMapper.cs
    ├─LinqBuilder
    | ├─Visitors
    | | └ParameterReplaceExpressionVisitor.cs
    | ├─Extensions
    | | └LinqExtensions.cs
    | ├─Builders
    | | └LinqExpression.cs
    ├─FriendlyException
    | ├─Oops.cs
    | ├─Providers
    | | └IErrorCodeTypeProvider.cs
    | ├─Options
    | | └ErrorCodeMessageSettingsOptions.cs
    | ├─Models
    | | └MethodIfException.cs
    | ├─Filters
    | | └FriendlyExceptionFilter.cs
    | ├─Extensions
    | | └FriendlyExceptionServiceCollectionExtensions.cs
    | ├─Attributes
    | | ├─ErrorCodeItemMetadataAttribute.cs
    | | ├─ErrorCodeTypeAttribute.cs
    | | └IfExceptionAttribute.cs
    ├─DynamicApiController
    | ├─Penetrates.cs
    | ├─Providers
    | | └DynamicApiControllerFeatureProvider.cs
    | ├─Options
    | | └DynamicApiControllerSettingsOptions.cs
    | ├─Models
    | | └ParameterRouteTemplate.cs
    | ├─Extensions
    | | └DynamicApiControllerServiceCollectionExtensions.cs
    | ├─Enums
    | | └ApiSeats.cs
    | ├─Dependencies
    | | └IDynamicApiController.cs
    | ├─Conventions
    | | └DynamicApiControllerApplicationModelConvention.cs
    | ├─Attributes
    | | ├─ApiDescriptionSettingsAttribute.cs
    | | ├─ApiSeatAttribute.cs
    | | └DynamicApiControllerAttribute.cs
    ├─DependencyInjection
    | ├─Extensions
    | | └DependencyInjectionServiceCollectionExtensions.cs
    | ├─Enums
    | | ├─InjectionActions.cs
    | | ├─InjectionPatterns.cs
    | | └RegisterType.cs
    | ├─Dependencies
    | | ├─IDependency.cs
    | | ├─IScoped.cs
    | | ├─ISingleton.cs
    | | ├─ITransient.cs
    | | ├─Aop
    | | | └IDispatchProxy.cs
    | ├─Attributes
    | | ├─InjectionAttribute.cs
    | | └SkipScanAttribute.cs
    ├─DataValidation
    | ├─Validators
    | | └DataValidator.cs
    | ├─Providers
    | | └IValidationMessageTypeProvider.cs
    | ├─Options
    | | └ValidationTypeMessageSettingsOptions.cs
    | ├─Models
    | | └DataValidationResult.cs
    | ├─Filters
    | | └DataValidationFilter.cs
    | ├─Extensions
    | | ├─DataValidationExtensions.cs
    | | └DataValidationServiceCollectionExtensions.cs
    | ├─Enums
    | | ├─ValidationPattern.cs
    | | └ValidationTypes.cs
    | ├─Attributes
    | | ├─DataValidationAttribute.cs
    | | ├─NonValidationAttribute.cs
    | | ├─ValidationItemMetadataAttribute.cs
    | | ├─ValidationMessageAttribute.cs
    | | ├─ValidationMessageTypeAttribute.cs
    | | └ValidationTypeAttribute.cs
    ├─DataEncryption
    | ├─AESEncryption.cs
    | ├─DESCEncryption.cs
    | └MD5Encryption.cs
    ├─DatabaseAccessor
    | ├─UnitOfWork
    | | ├─Filters
    | | | └UnitOfWorkFilter.cs
    | | ├─Attributes
    | | | ├─NonTransactAttribute.cs
    | | | └UnitOfWorkAttribute.cs
    | ├─Repositories
    | | ├─EFCoreRepository.cs
    | | ├─IMSRepository.cs
    | | ├─IRepository.cs
    | | ├─ISqlRepository.cs
    | | ├─MSRepository.cs
    | | ├─SqlRepository.cs
    | | ├─Implantations
    | | | ├─DeletableRepository.cs
    | | | ├─InsertableRepository.cs
    | | | ├─OperableRepository.cs
    | | | ├─ReadableRepository.cs
    | | | ├─SqlExecutableRepository.cs
    | | | ├─SqlReaderRepository.cs
    | | | ├─UpdateableRepository.cs
    | | | └WritableRepository.cs
    | | ├─Dependencies
    | | | ├─IDeletableRepository.cs
    | | | ├─IInsertableRepository.cs
    | | | ├─IOperableRepository.cs
    | | | ├─IReadableRepository.cs
    | | | ├─IRepositoryDependency.cs
    | | | ├─ISqlExecutableRepository.cs
    | | | ├─ISqlReaderRepository.cs
    | | | ├─IUpdateableRepository.cs
    | | | └IWritableRepository.cs
    | ├─Pools
    | | ├─DbContextPool.cs
    | | └IDbContextPool.cs
    | ├─Options
    | | └DatabaseAccessorSettingsOptions.cs
    | ├─MultiTenants
    | | ├─Providers
    | | | ├─IMultiTenantOnDatabaseProvider.cs
    | | | ├─IMultiTenantOnSchemaProvider.cs
    | | | ├─IMultiTenantOnTableProvider.cs
    | | | └IMultiTenantProviderDependency.cs
    | | ├─Locators
    | | | └MultiTenantDbContextLocator.cs
    | | ├─Enums
    | | | └MultiTenantOptions.cs
    | | ├─Entities
    | | | └Tenant.cs
    | ├─Models
    | | ├─DbProvider.cs
    | | ├─PagedList.cs
    | | ├─ProcedureOutputResult.cs
    | | └ProcedureOutputValue.cs
    | ├─Locators
    | | ├─IDbContextLocator.cs
    | | └MasterDbContextLocator.cs
    | ├─Interceptors
    | | ├─DbContextSaveChangesInterceptor.cs
    | | ├─SqlCommandProfilerInterceptor.cs
    | | └SqlConnectionProfilerInterceptor.cs
    | ├─Helpers
    | | └DbHelpers.cs
    | ├─Extensions
    | | ├─DatabaseAccessorServiceCollectionExtensions.cs
    | | ├─PagedQueryableExtensions.cs
    | | ├─Repositories
    | | | ├─IEntityDbContextLocatorExtensions.cs
    | | | ├─IEntityExtensions.cs
    | | | └SqlExtensions.cs
    | | ├─DatabaseProvider
    | | | ├─DatabaseProviderServiceCollectionExtensions.cs
    | | | └Penetrates.cs
    | | ├─DatabaseFacade
    | | | ├─DbDataConvertExtensions.cs
    | | | ├─DbObjectExtensions.cs
    | | | └SqlAdoNetExtensions.cs
    | ├─Enums
    | | ├─DbFunctionType.cs
    | | ├─EFCoreErrorCodes.cs
    | | └ManualOptions.cs
    | ├─Entities
    | | ├─Dependencies
    | | | ├─Entity.cs
    | | | ├─EntityBase.cs
    | | | ├─EntityNotKey.cs
    | | | ├─IEntity.cs
    | | | └IEntityNotKey.cs
    | | ├─Configures
    | | | ├─IEntitySeedData.cs
    | | | ├─IEntityTypeBuilder.cs
    | | | ├─IModelBuilderDependency.cs
    | | | └IModelBuilderFilter.cs
    | | ├─Attributes
    | | | ├─FakeDeleteAttribute.cs
    | | | ├─NonAutomaticAttribute.cs
    | | | └QueryableFunctionAttribute.cs
    | ├─DynamicModels
    | | ├─DynamicModelCacheKeyFactory.cs
    | | └IEntityMutableTable.cs
    | ├─Contexts
    | | ├─AppDbContext.cs
    | | ├─Builders
    | | | ├─AppDbContextBuilder.cs
    | | | ├─Models
    | | | | └DbContextCorrelationType.cs
    | | ├─Attributes
    | | | └DbContextAttribute.cs
    | ├─Attributes
    | | └DbParameterAttribute.cs
    | ├─Advances
    | | ├─Proxies
    | | | └SqlDispatchProxy.cs
    | | ├─Models
    | | | └SqlProxyMethod.cs
    | | ├─Dependencies
    | | | └ISqlDispatchProxy.cs
    | | ├─Attributes
    | | | ├─SqlExecuteAttribute.cs
    | | | ├─SqlFunctionAttribute.cs
    | | | ├─SqlProcedureAttribute.cs
    | | | ├─Basics
    | | | | ├─SqlObjectProxyAttribute.cs
    | | | | ├─SqlProxyAttribute.cs
    | | | | └SqlSentenceProxyAttribute.cs
    ├─CorsAccessor
    | ├─Options
    | | └CorsAccessorSettingsOptions.cs
    | ├─Extensions
    | | ├─CorsAccessorApplicationBuilderExtensions.cs
    | | └CorsAccessorServiceCollectionExtensions.cs
    ├─ConfigurableOptions
    | ├─Options
    | | └IConfigurableOptions.cs
    | ├─Extensions
    | | └ConfigurableOptionsServiceCollectionExtensions.cs
    | ├─Attributes
    | | └OptionsSettingsAttribute.cs
    ├─Authorization
    | ├─Penetrates.cs
    | ├─Requirements
    | | └AuthorizePolicyRequirement.cs
    | ├─Providers
    | | └AuthorizePolicyProvider.cs
    | ├─Options
    | | └JWTSettingsOptions.cs
    | ├─Handlers
    | | └AuthorizePolicyHandler.cs
    | ├─Extensions
    | | └PolicyAuthorizationServiceCollectionExtensions.cs
    | ├─Attributes
    | | └AuthorizePolicyAttribute.cs
    ├─App
    | ├─App.cs
    | ├─Startups
    | | ├─AppStartup.cs
    | | └HostingStartup.cs
    | ├─Options
    | | └AppSettingsOptions.cs
    | ├─Filters
    | | └StartupFilter.cs
    | ├─Extensions
    | | ├─AppApplicationBuilderExtensions.cs
    | | ├─AppServiceCollectionExtensions.cs
    | | └ObjectExtensions.cs
    | ├─Attributes
    | | └StartupAttribute.cs

    1.2.5 Fur.Application 业务应用层

    Fur.Application 业务应用层是最常用的层,几乎所有的业务代码都在这个层中编写。

    源码结构:

    Fur.Application
    ├─Fur.Application.Core.csproj
    ├─Fur.Application.Core.xml
    └FurApplicationStartup.cs

    1.2.6 Fur.Core 仓储实体层

    Fur.Core 主要是存储自定义仓储和定义实体的层。

    源码结构:

    Fur.Core
    ├─Fur.Core.csproj
    └FurCoreStartup.cs

    1.2.7 Fur.Database.Migrations 数据库架构维护层

    Fur.Database.Migrations 主要是用来存放 Database FirstCode First 生成的维护文件。

    源码结构:

    Fur.Database.Migrations
    └Fur.Database.Migrations.csproj

    1.2.8 Fur.EntityFramework.Core 数据库上下文配置层

    Fur.EntityFramework.Core 主要是用来配置数据库上下文和其他数据库相关配置信息的。

    源码结构:

    Fur.EntityFramework.Core
    └Fur.EntityFramework.Core.csproj

    1.2.9 Fur.Web.Core 应用核心层

    Fur.Web.Core 主要是用来配置 Web 入口一些代码,如 FilterMiddlewares 等。

    源码结构:

    Fur.Web.Core
    ├─Fur.Web.Core.xml
    └FurWebCoreStartup.cs

    1.2.10 Fur.Web.Entry 应用入口层

    Fur.Web.Entry 是我们的应用层,也就是我们的 Web 项目层,发布层。

    源码结构:

    Fur.Web.Entry
    ├─appsettings.Development.json
    ├─appsettings.json
    ├─Fur.Web.Entry.csproj
    ├─Fur.Web.Entry.csproj.user
    ├─Fur.Web.Entry.xml
    ├─Program.cs
    ├─Startup.cs
    ├─wwwroot
    | └README.md
    ├─Properties
    | └launchSettings.json
    ├─Controllers
    - + diff --git a/docs/docs/specification-document/index.html b/docs/docs/specification-document/index.html index 7ac7d983ddb..884875fd288 100644 --- a/docs/docs/specification-document/index.html +++ b/docs/docs/specification-document/index.html @@ -6,7 +6,7 @@ 6. 规范化接口文档 | Fur - + @@ -51,7 +51,7 @@
    "Requirement": {
    "Scheme": {
    "Reference": {
    "Id": "Bearer",
    "Type": "SecurityScheme"
    },
    "Accesses": null
    }
    }
    }
    ]
    }
    }
    }

    6.5.12 在线测试

    如下图所示:

    6.5.13 性能监视 MiniProfiler

    规范化文档默认集成了 MiniProfiler 第三方性能组件,通过该组件可以方便查看请求性能、异常堆栈、数据库操作等信息。默认在 Swagger 首页左上角显示。

    如下图所示:

    小提示

    也可以通过 appsetting.jsonAppSettings:InjectMiniProfiler 设为 false 关闭。

    6.5.14 定义接口输出类型

    using Fur.DynamicApiController;
    using Microsoft.AspNetCore.Mvc;
    namespace Fur.Application
    {
    public class FurAppService : IDynamicApiController
    {
    [ProducesResponseType(201, Type = typeof(TestDto))]
    [ProducesResponseType(400)]
    public string Get()
    {
    return nameof(Fur);
    }
    }
    }

    如下图所示:

    6.6 SpecificationDocumentSettings 配置

    除了上述例子外,Fur 提供了一些配置选项,如:

    • DocumentTitle:文档标题,string,默认 Specification Api Document
    • DefaultGroupName:默认分组名,string,默认 Default
    • EnableAuthorized:是否启用权限控制,bool,默认 true
    • FormatAsV2:采用 Swagger 2.0 版本,bool,默认 false
    • RoutePrefix:规范化文档地址,string,默认 string
    • DocExpansionState:文档显示方式,DocExpansion,默认 List,取值:
      • List:列表式(展开子类),默认值
      • Full:完全展开
      • None:列表式(不展开子类)
    • XmlComments:程序集注释描述文件名(可带 .xmlstring,默认 Fur.Application, Fur.Web.Entry, Fur.Web.Core
    • GroupOpenApiInfos:分组信息配置,SpecificationOpenApiInfo[],默认 { 'Group': 'Default'}
    • SecurityDefinitions:安全策略定义配置,SpecificationOpenApiSecurityScheme[],默认 []

    6.7 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/docs/docs/split-db/index.html b/docs/docs/split-db/index.html index 54128a74c54..5a5414ce9f1 100644 --- a/docs/docs/split-db/index.html +++ b/docs/docs/split-db/index.html @@ -6,7 +6,7 @@ 9.27 分表分库 | Fur - + @@ -30,7 +30,7 @@
    // 通过数据库上下文定位器切换
    repository.Change<Entity, MyDbContextLocator2>();

    如需跨库查询,需用到数据库技术,如 SqlServer 链接服务器或同义词。

    • 动态切换数据库表
    // 直接改变表,会有多线程操作bug,同时无法刷新模型
    repository.ChangeTable("数据库表");
    // 创建新的 DbContext,然后刷新 OnModelCreating(推荐方式)
    var dynamicDbContextResolve = App.TransientServices.GetService<Func<Type, IScoped, DbContext>>();
    var dynamicDbContext = dynamicDbContextResolve(typeof(MyDbContextLocator), default);
    // 重新调用 OnModelCreating,在 OnModelCreating 中配置 ToTable("动态表") 即可。
    DynamicModelCacheKeyFactory.RebuildModels();
    var persons= dynamicDbContext.Set<Person>();
    persons.Add(new Person{});
    了解更多

    想了解更多 DynamicModelCacheKeyFactory 知识可查阅 EF Core - 多个模型之间交替 章节。

    9.27.7 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/docs/docs/tran/index.html b/docs/docs/tran/index.html index 2a850705442..45a41082519 100644 --- a/docs/docs/tran/index.html +++ b/docs/docs/tran/index.html @@ -6,7 +6,7 @@ 9.25 事务和工作单元 | Fur - + @@ -29,7 +29,7 @@
    var blogs = _testRepository.Entity
    .OrderBy(b => b.Url)
    .ToList();
    // 提交事务
    transaction.Commit();
    }
    catch (Exception)
    {
    // 回滚事务
    transaction.RollBack();
    }
    }

    9.25.4 工作单元特性说明

    9.25.4.1 [UnitOfWork]

    [UnitOfWork] 特性用来标记事务信息,如作用范围,隔离级别等。

    • Enabled:是否启动工作单元,默认 true
    • ScopeOption:定义事务范围行为,默认 TransactionScopeOption.Required
    • IsolationLevel:设置事务隔离级别,默认 IsolationLevel.ReadCommitted;
    • AsyncFlowOption:允许跨线程连续任务的事务流,如有异步操作需开启该选项,默认开启
    特别注意

    一旦方法贴了 [UnitOfWork(false)] 特性后,那么该方法不再启用工作单元模式,也就是不包含事务,也不会自动提交数据库。慎用!

    9.25.4.2 [NonTransact]

    一但方法或类贴了 [NonTransact] 特性,那么将关闭事务操作,但是还是会自动保存数据库到数据。

    9.25.5 常见错误

    • A TransactionScope must be disposed on the same thread that it was created.

    只需要在当前操作方法上贴 [NonTransact] 特性即可。

    9.25.6 反馈与建议

    与我们交流

    给 Fur 提 Issue


    了解更多

    想了解更多 事务 知识可查阅 EF Core - 使用事务 章节。

    - + diff --git a/docs/docs/unittest/index.html b/docs/docs/unittest/index.html index 27aee447adf..dbb8d376224 100644 --- a/docs/docs/unittest/index.html +++ b/docs/docs/unittest/index.html @@ -6,7 +6,7 @@ 27.1 单元测试 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/docs/docs/view-engine/index.html b/docs/docs/view-engine/index.html index 22b9597bd44..20b9ebace43 100644 --- a/docs/docs/view-engine/index.html +++ b/docs/docs/view-engine/index.html @@ -6,7 +6,7 @@ 17. 视图引擎 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/docs/f9353588.f01f83d1.js b/docs/f9353588.f01f83d1.js new file mode 100644 index 00000000000..4bbb4446832 --- /dev/null +++ b/docs/f9353588.f01f83d1.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[75],{130:function(e,n,t){"use strict";t.r(n),t.d(n,"frontMatter",(function(){return s})),t.d(n,"metadata",(function(){return c})),t.d(n,"rightToc",(function(){return p})),t.d(n,"default",(function(){return b}));var r=t(2),a=t(6),i=(t(0),t(138)),o=t(140),s={id:"get-start",title:"2. \u4e00\u5206\u949f\u5165\u95e8",sidebar_label:"2. \u4e00\u5206\u949f\u5165\u95e8"},c={unversionedId:"get-start",id:"get-start",isDocsHomePage:!1,title:"2. \u4e00\u5206\u949f\u5165\u95e8",description:"2.1 Hello Fur",source:"@site/docs\\get-start.mdx",slug:"/get-start",permalink:"/docs/get-start",editUrl:"https://gitee.com/monksoul/Fur/tree/main/handbook/docs/get-start.mdx",version:"current",sidebar_label:"2. \u4e00\u5206\u949f\u5165\u95e8",sidebar:"docs",previous:{title:"1.3 \u5173\u4e8e\u4f5c\u8005",permalink:"/docs/author"},next:{title:"3. \u5e94\u7528\u542f\u52a8",permalink:"/docs/appstartup"}},p=[{value:"2.1 Hello Fur",id:"21-hello-fur",children:[{value:"2.1.1 \u521b\u5efa FurService \u7c7b",id:"211-\u521b\u5efa-furservice-\u7c7b",children:[]},{value:"2.1.2 \u5728\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b\u6548\u679c",id:"212-\u5728\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b\u6548\u679c",children:[]}]},{value:"2.2 \u6dfb\u52a0\u6570\u636e\u5e93\u652f\u6301",id:"22-\u6dfb\u52a0\u6570\u636e\u5e93\u652f\u6301",children:[{value:"2.2.1 \u6dfb\u52a0 Person \u5b9e\u4f53\u7c7b",id:"221-\u6dfb\u52a0-person-\u5b9e\u4f53\u7c7b",children:[]},{value:"2.2.2 \u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"222-\u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"2.2.3 \u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"223-\u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"2.2.4 \u901a\u8fc7\u547d\u4ee4\u521b\u5efa\u6570\u636e\u5e93\u8868",id:"224-\u901a\u8fc7\u547d\u4ee4\u521b\u5efa\u6570\u636e\u5e93\u8868",children:[]}]},{value:"2.3 \u589e\u5220\u67e5\u6539\u5206\u9875\u4f8b\u5b50",id:"23-\u589e\u5220\u67e5\u6539\u5206\u9875\u4f8b\u5b50",children:[{value:"\u9644\u4e0a PersonDto",id:"\u9644\u4e0a-persondto",children:[]}]}],u={rightToc:p};function b(e){var n=e.components,t=Object(a.a)(e,["components"]);return Object(i.b)("wrapper",Object(r.a)({},u,t,{components:n,mdxType:"MDXLayout"}),Object(i.b)("h2",{id:"21-hello-fur"},"2.1 Hello Fur"),Object(i.b)("h3",{id:"211-\u521b\u5efa-furservice-\u7c7b"},"2.1.1 \u521b\u5efa ",Object(i.b)("inlineCode",{parentName:"h3"},"FurService")," \u7c7b"),Object(i.b)("p",null,"\u8bbe\u7f6e ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Web.Entry")," \u4e3a\u542f\u52a8\u9879\uff0c\u5e76\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Application")," \u4e2d\u521b\u5efa ",Object(i.b)("inlineCode",{parentName:"p"},"FurService")," \u7c7b\uff0c\u5e76\u8f93\u5165\u4ee5\u4e0b\u5185\u5bb9:"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs",metastring:"{1,5,6,12}","{1,5,6,12}":!0}),'using Fur.DynamicApiController;\n\nnamespace Fur.Application\n{\n [DynamicApiController] // \u8fd9\u91cc\u4f7f\u7528\u7279\u6027\u65b9\u5f0f\n public class FurService /*: IDynamicApiController*/ // \u4e5f\u53ef\u4ee5\u4f7f\u7528\u63a5\u53e3\u65b9\u5f0f\n {\n /// \n /// \u5411\u4e16\u754c\u95ee\u597d\n /// \n /// \n public string SayHello()\n {\n return $"Hello {nameof(Fur)}";\n }\n }\n}\n')),Object(i.b)("h3",{id:"212-\u5728\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b\u6548\u679c"},"2.1.2 \u5728\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b\u6548\u679c"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Web.Entry")," \u9879\u76ee\u4e2d\u9009\u62e9 ",Object(i.b)("inlineCode",{parentName:"p"},"wwwroot")," \u53f3\u952e\u9009\u62e9\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b")),Object(i.b)("img",{src:Object(o.a)("img/getstart1.png"),style:{height:400}}),Object(i.b)("p",null,"\u6548\u679c\u5982\u4e0b\uff1a"),Object(i.b)("img",{src:Object(o.a)("img/getstart2.gif")}),Object(i.b)("h2",{id:"22-\u6dfb\u52a0\u6570\u636e\u5e93\u652f\u6301"},"2.2 \u6dfb\u52a0\u6570\u636e\u5e93\u652f\u6301"),Object(i.b)("h3",{id:"221-\u6dfb\u52a0-person-\u5b9e\u4f53\u7c7b"},"2.2.1 \u6dfb\u52a0 ",Object(i.b)("inlineCode",{parentName:"h3"},"Person")," \u5b9e\u4f53\u7c7b"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Core")," \u4e2d\u65b0\u5efa ",Object(i.b)("inlineCode",{parentName:"p"},"Person")," \u5b9e\u4f53\u7c7b\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs",metastring:"{1,7}","{1,7}":!0}),"using Fur.DatabaseAccessor;\nusing System;\nusing System.ComponentModel.DataAnnotations;\n\nnamespace Fur.Core\n{\n public class Person : Entity // \u7ee7\u627f\u81ea Entity \u62bd\u8c61\u7c7b\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")),Object(i.b)("h3",{id:"222-\u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"2.2.2 \u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u4e2d\u6dfb\u52a0 ",Object(i.b)("inlineCode",{parentName:"p"},"FurDbContext")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs",metastring:"{1-2,6-7,13}","{1-2,6-7,13}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Data Source=./Fur.db")] // \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32\n public class FurDbContext : AppDbContext // \u7ee7\u627f AppDbContext<> \u7c7b\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(i.b)("h3",{id:"223-\u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"2.2.3 \u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u7684 ",Object(i.b)("inlineCode",{parentName:"p"},"FurEntityFrameworkCoreStartup")," \u4e2d\u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs",metastring:'{11-14} title="Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"',"{11-14}":!0,title:'"Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"'}),"using Fur.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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")),Object(i.b)("div",{className:"admonition admonition-important alert alert--info"},Object(i.b)("div",Object(r.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(r.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(r.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(r.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u8bf4\u660e")),Object(i.b)("div",Object(r.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6f14\u793a\u793a\u4f8b\u4e2d\uff0c\u9ed8\u8ba4\u5df2\u7ecf\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u5c42\u5b89\u88c5\u4e86 ",Object(i.b)("inlineCode",{parentName:"p"},"Microsoft.EntityFrameworkCore.Sqlite")," \u5305\u3002"),Object(i.b)("p",{parentName:"div"},"\u5982\u679c\u4f60\u9700\u8981\u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93\u7248\u672c\uff0c\u53ef\u4ee5\u67e5\u9605 \u3010",Object(i.b)("a",Object(r.a)({parentName:"p"},{href:"dbcontext-multi-database"}),"9.18 \u591a\u6570\u636e\u5e93\u64cd\u4f5c"),"\u3011 \u7ae0\u8282\u3002"))),Object(i.b)("h3",{id:"224-\u901a\u8fc7\u547d\u4ee4\u521b\u5efa\u6570\u636e\u5e93\u8868"},"2.2.4 \u901a\u8fc7\u547d\u4ee4\u521b\u5efa\u6570\u636e\u5e93\u8868"),Object(i.b)("p",null,"\u6253\u5f00 ",Object(i.b)("inlineCode",{parentName:"p"},"\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0"),"\uff0c\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),Object(i.b)("img",{src:Object(o.a)("img/getstart3.png"),style:{height:400}}),Object(i.b)("p",null,"\u9009\u62e9 ",Object(i.b)("inlineCode",{parentName:"p"},"\u9ed8\u8ba4\u9879\u76ee\u4e3a"),"\uff1a",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Database.Migrations"),"\uff0c\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),Object(i.b)("img",{src:Object(o.a)("img/getstart4.png")}),Object(i.b)("p",null,Object(i.b)("strong",{parentName:"p"},"\u8f93\u5165\u4ee5\u4e0b\u547d\u4ee4"),"\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{}),"Add-Migration v0.0.1\n")),Object(i.b)("img",{src:Object(o.a)("img/getstart5.png")}),Object(i.b)("p",null,Object(i.b)("strong",{parentName:"p"},"\u63d0\u4ea4\u5230\u6570\u636e\u5e93\u66f4\u6539")),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{}),"Update-Database\n")),Object(i.b)("img",{src:Object(o.a)("img/getstart6.png")}),Object(i.b)("img",{src:Object(o.a)("img/getstart7.png"),style:{height:400}}),Object(i.b)("h2",{id:"23-\u589e\u5220\u67e5\u6539\u5206\u9875\u4f8b\u5b50"},"2.3 \u589e\u5220\u67e5\u6539\u5206\u9875\u4f8b\u5b50"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs",metastring:"{14-19}","{14-19}":!0}),'using Fur.Core;\nusing Fur.DatabaseAccessor;\nusing Fur.DynamicApiController;\nusing Mapster;\nusing Microsoft.EntityFrameworkCore;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\n\nnamespace Fur.Application\n{\n [DynamicApiController] // \u8fd9\u91cc\u4f7f\u7528\u7279\u6027\u65b9\u5f0f\n public class FurService /*: IDynamicApiController*/ // \u4e5f\u53ef\u4ee5\u4f7f\u7528\u63a5\u53e3\u65b9\u5f0f\n {\n // \u521d\u59cb\u5316\u4ed3\u50a8\n private readonly IRepository _personRepository;\n public FurService(IRepository personRepository)\n {\n _personRepository = personRepository;\n }\n\n /// \n /// \u65b0\u589e\u4e00\u6761\n /// \n public async Task Insert(PersonDto personDto)\n {\n // \u5982\u679c\u4e0d\u9700\u8981\u8fd4\u56de\u81ea\u589eId\uff0c\u4f7f\u7528 InsertAsync\u5373\u53ef\n var newEntity = await _personRepository.InsertNowAsync(personDto.Adapt());\n return newEntity.Entity.Id;\n\n // \u8fd8\u53ef\u4ee5\u76f4\u63a5\u64cd\u4f5c\n // await personDto.Adapt().InsertNowAsync();\n }\n\n /// \n /// \u66f4\u65b0\u4e00\u6761\n /// \n /// \n public async Task Update(PersonDto personDto)\n {\n await _personRepository.UpdateAsync(personDto.Adapt());\n\n // \u8fd8\u53ef\u4ee5\u76f4\u63a5\u64cd\u4f5c\n // await personDto.Adapt().UpdateAsync();\n }\n\n /// \n /// \u5220\u9664\u4e00\u6761\n /// \n /// \n public async Task Delete(int id)\n {\n await _personRepository.DeleteAsync(id);\n }\n\n /// \n /// \u67e5\u8be2\u4e00\u6761\n /// \n /// \n public async Task Find(int id)\n {\n var person = await _personRepository.FindAsync(id);\n return person.Adapt();\n }\n\n /// \n /// \u67e5\u8be2\u6240\u6709\n /// \n /// \n public async Task> GetAll()\n {\n var persons = await _personRepository.AsAsyncEnumerable();\n return persons.Adapt>();\n }\n\n /// \n /// \u5206\u9875\u67e5\u8be2\n /// \n /// \n /// \n /// \n public async Task> GetAllByPage(int pageIndex = 1, int pageSize = 10)\n {\n var pageResult = await _personRepository.AsQueryable().ToPagedListAsync(pageIndex, pageSize);\n return pageResult.Adapt>();\n }\n }\n}\n')),Object(i.b)("img",{src:Object(o.a)("img/getstart8.gif")}),Object(i.b)("h3",{id:"\u9644\u4e0a-persondto"},"\u9644\u4e0a ",Object(i.b)("inlineCode",{parentName:"h3"},"PersonDto")),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs"}),"using System.ComponentModel.DataAnnotations;\n\nnamespace Fur.Application\n{\n public class PersonDto\n {\n /// \n /// Id\n /// \n public int? Id { get; set; }\n\n /// \n /// \u59d3\u540d\n /// \n [StringLength(32, MinimumLength = 2)]\n public string Name { get; set; }\n\n /// \n /// \u5e74\u9f84\n /// \n public int Age { get; set; }\n }\n}\n")),Object(i.b)("p",null,"\u8bf4\u597d\u4e00\u5206\u949f\u5165\u95e8\uff0c\u4f60\u4eec\u7528\u4e86\u591a\u957f\u65f6\u95f4\u3002\ud83d\ude01"))}b.isMDXComponent=!0},138:function(e,n,t){"use strict";t.d(n,"a",(function(){return b})),t.d(n,"b",(function(){return d}));var r=t(0),a=t.n(r);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 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 p=a.a.createContext({}),u=function(e){var n=a.a.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},b=function(e){var n=u(e.components);return a.a.createElement(p.Provider,{value:n},e.children)},l={inlineCode:"code",wrapper:function(e){var n=e.children;return a.a.createElement(a.a.Fragment,{},n)}},m=a.a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,i=e.originalType,o=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),b=u(t),m=r,d=b["".concat(o,".").concat(m)]||b[m]||l[m]||i;return t?a.a.createElement(d,s(s({ref:n},p),{},{components:t})):a.a.createElement(d,s({ref:n},p))}));function d(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var i=t.length,o=new Array(i);o[0]=m;var s={};for(var c in n)hasOwnProperty.call(n,c)&&(s[c]=n[c]);s.originalType=e,s.mdxType="string"==typeof e?e:r,o[1]=s;for(var p=2;pfunction(e,n,t,{forcePrependBaseUrl:r=!1,absolute:i=!1}={}){if(!t)return t;if(t.startsWith("#"))return t;if(Object(a.b)(t))return t;if(r)return n+t;const o=t.startsWith(n)?t:n+t.replace(/^\//,"");return i?e+o:o}(n,e,t,r)}}function o(e,n={}){const{withBaseUrl:t}=i();return t(e,n)}},141:function(e,n,t){"use strict";function r(e){return!0===/^(\w*:|\/\/)/.test(e)}function a(e){return void 0!==e&&!r(e)}t.d(n,"b",(function(){return r})),t.d(n,"a",(function(){return a}))}}]); \ No newline at end of file diff --git a/docs/f9353588.f7d5daf4.js b/docs/f9353588.f7d5daf4.js deleted file mode 100644 index 0b112bda503..00000000000 --- a/docs/f9353588.f7d5daf4.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[75],{130:function(e,n,t){"use strict";t.r(n),t.d(n,"frontMatter",(function(){return s})),t.d(n,"metadata",(function(){return c})),t.d(n,"rightToc",(function(){return p})),t.d(n,"default",(function(){return b}));var r=t(2),a=t(6),i=(t(0),t(138)),o=t(140),s={id:"get-start",title:"2. \u4e00\u5206\u949f\u5165\u95e8",sidebar_label:"2. \u4e00\u5206\u949f\u5165\u95e8"},c={unversionedId:"get-start",id:"get-start",isDocsHomePage:!1,title:"2. \u4e00\u5206\u949f\u5165\u95e8",description:"2.1 Hello Fur",source:"@site/docs\\get-start.mdx",slug:"/get-start",permalink:"/docs/get-start",editUrl:"https://gitee.com/monksoul/Fur/tree/main/handbook/docs/get-start.mdx",version:"current",sidebar_label:"2. \u4e00\u5206\u949f\u5165\u95e8",sidebar:"docs",previous:{title:"1.3 \u5173\u4e8e\u4f5c\u8005",permalink:"/docs/author"},next:{title:"3. \u5e94\u7528\u542f\u52a8",permalink:"/docs/appstartup"}},p=[{value:"2.1 Hello Fur",id:"21-hello-fur",children:[{value:"2.1.1 \u521b\u5efa FurService \u7c7b",id:"211-\u521b\u5efa-furservice-\u7c7b",children:[]},{value:"2.1.2 \u5728\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b\u6548\u679c",id:"212-\u5728\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b\u6548\u679c",children:[]}]},{value:"2.2 \u6dfb\u52a0\u6570\u636e\u5e93\u652f\u6301",id:"22-\u6dfb\u52a0\u6570\u636e\u5e93\u652f\u6301",children:[{value:"2.2.1 \u6dfb\u52a0 Person \u5b9e\u4f53\u7c7b",id:"221-\u6dfb\u52a0-person-\u5b9e\u4f53\u7c7b",children:[]},{value:"2.2.2 \u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"222-\u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"2.2.3 \u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32",id:"223-\u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32",children:[]},{value:"2.2.4 \u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"224-\u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"2.2.5 \u901a\u8fc7\u547d\u4ee4\u521b\u5efa\u6570\u636e\u5e93\u8868",id:"225-\u901a\u8fc7\u547d\u4ee4\u521b\u5efa\u6570\u636e\u5e93\u8868",children:[]}]},{value:"2.3 \u589e\u5220\u67e5\u6539\u5206\u9875\u4f8b\u5b50",id:"23-\u589e\u5220\u67e5\u6539\u5206\u9875\u4f8b\u5b50",children:[{value:"\u9644\u4e0a PersonDto",id:"\u9644\u4e0a-persondto",children:[]}]}],u={rightToc:p};function b(e){var n=e.components,t=Object(a.a)(e,["components"]);return Object(i.b)("wrapper",Object(r.a)({},u,t,{components:n,mdxType:"MDXLayout"}),Object(i.b)("h2",{id:"21-hello-fur"},"2.1 Hello Fur"),Object(i.b)("h3",{id:"211-\u521b\u5efa-furservice-\u7c7b"},"2.1.1 \u521b\u5efa ",Object(i.b)("inlineCode",{parentName:"h3"},"FurService")," \u7c7b"),Object(i.b)("p",null,"\u8bbe\u7f6e ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Web.Entry")," \u4e3a\u542f\u52a8\u9879\uff0c\u5e76\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Application")," \u4e2d\u521b\u5efa ",Object(i.b)("inlineCode",{parentName:"p"},"FurService")," \u7c7b\uff0c\u5e76\u8f93\u5165\u4ee5\u4e0b\u5185\u5bb9:"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs",metastring:"{1,5,6,12}","{1,5,6,12}":!0}),'using Fur.DynamicApiController;\n\nnamespace Fur.Application\n{\n [DynamicApiController] // \u8fd9\u91cc\u4f7f\u7528\u7279\u6027\u65b9\u5f0f\n public class FurService /*: IDynamicApiController*/ // \u4e5f\u53ef\u4ee5\u4f7f\u7528\u63a5\u53e3\u65b9\u5f0f\n {\n /// \n /// \u5411\u4e16\u754c\u95ee\u597d\n /// \n /// \n public string SayHello()\n {\n return $"Hello {nameof(Fur)}";\n }\n }\n}\n')),Object(i.b)("h3",{id:"212-\u5728\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b\u6548\u679c"},"2.1.2 \u5728\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b\u6548\u679c"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Web.Entry")," \u9879\u76ee\u4e2d\u9009\u62e9 ",Object(i.b)("inlineCode",{parentName:"p"},"wwwroot")," \u53f3\u952e\u9009\u62e9\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b")),Object(i.b)("img",{src:Object(o.a)("img/getstart1.png"),style:{height:400}}),Object(i.b)("p",null,"\u6548\u679c\u5982\u4e0b\uff1a"),Object(i.b)("img",{src:Object(o.a)("img/getstart2.gif")}),Object(i.b)("h2",{id:"22-\u6dfb\u52a0\u6570\u636e\u5e93\u652f\u6301"},"2.2 \u6dfb\u52a0\u6570\u636e\u5e93\u652f\u6301"),Object(i.b)("h3",{id:"221-\u6dfb\u52a0-person-\u5b9e\u4f53\u7c7b"},"2.2.1 \u6dfb\u52a0 ",Object(i.b)("inlineCode",{parentName:"h3"},"Person")," \u5b9e\u4f53\u7c7b"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Core")," \u4e2d\u65b0\u5efa ",Object(i.b)("inlineCode",{parentName:"p"},"Person")," \u5b9e\u4f53\u7c7b\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs",metastring:"{1,7}","{1,7}":!0}),"using Fur.DatabaseAccessor;\nusing System;\nusing System.ComponentModel.DataAnnotations;\n\nnamespace Fur.Core\n{\n public class Person : Entity // \u7ee7\u627f\u81ea Entity \u62bd\u8c61\u7c7b\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")),Object(i.b)("h3",{id:"222-\u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"2.2.2 \u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u4e2d\u6dfb\u52a0 ",Object(i.b)("inlineCode",{parentName:"p"},"FurDbContext")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs",metastring:"{1-2,6-7,13}","{1-2,6-7,13}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("DbConnectionString")] // \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32\n public class FurDbContext : AppDbContext // \u7ee7\u627f AppDbContext<> \u7c7b\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(i.b)("h3",{id:"223-\u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32"},"2.2.3 \u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u7684 ",Object(i.b)("inlineCode",{parentName:"p"},"dbsettings.json")," \u4e2d\u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-json",metastring:'{2-4} title="Fur\\framework\\Fur.EntityFramework.Core\\dbsettings.json"',"{2-4}":!0,title:'"Fur\\framework\\Fur.EntityFramework.Core\\dbsettings.json"'}),'{\n "ConnectionStrings": {\n "DbConnectionString": "Server=localhost;Database=Fur;User=sa;Password=000000;MultipleActiveResultSets=True;",\n "Sqlite3ConnectionString": "Data Source=./Fur.db"\n }\n}\n')),Object(i.b)("h3",{id:"224-\u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"2.2.4 \u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u7684 ",Object(i.b)("inlineCode",{parentName:"p"},"FurEntityFrameworkCoreStartup")," \u4e2d\u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs",metastring:'{12-14} title="Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"',"{12-14}":!0,title:'"Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"'}),"using Fur.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.EntityFramework.Core\n{\n [Startup(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 options.AddDbPool(DbProvider.Sqlite);\n });\n }\n }\n}\n")),Object(i.b)("div",{className:"admonition admonition-important alert alert--info"},Object(i.b)("div",Object(r.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(r.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(r.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(r.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u8bf4\u660e")),Object(i.b)("div",Object(r.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6f14\u793a\u793a\u4f8b\u4e2d\uff0c\u9ed8\u8ba4\u5df2\u7ecf\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u5c42\u5b89\u88c5\u4e86 ",Object(i.b)("inlineCode",{parentName:"p"},"Microsoft.EntityFrameworkCore.Sqlite")," \u5305\u3002"),Object(i.b)("p",{parentName:"div"},"\u5982\u679c\u4f60\u9700\u8981\u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93\u7248\u672c\uff0c\u53ef\u4ee5\u67e5\u9605 \u3010",Object(i.b)("a",Object(r.a)({parentName:"p"},{href:"dbcontext-multi-database"}),"9.18 \u591a\u6570\u636e\u5e93\u64cd\u4f5c"),"\u3011 \u7ae0\u8282\u3002"))),Object(i.b)("h3",{id:"225-\u901a\u8fc7\u547d\u4ee4\u521b\u5efa\u6570\u636e\u5e93\u8868"},"2.2.5 \u901a\u8fc7\u547d\u4ee4\u521b\u5efa\u6570\u636e\u5e93\u8868"),Object(i.b)("p",null,"\u6253\u5f00 ",Object(i.b)("inlineCode",{parentName:"p"},"\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0"),"\uff0c\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),Object(i.b)("img",{src:Object(o.a)("img/getstart3.png"),style:{height:400}}),Object(i.b)("p",null,"\u9009\u62e9 ",Object(i.b)("inlineCode",{parentName:"p"},"\u9ed8\u8ba4\u9879\u76ee\u4e3a"),"\uff1a",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Database.Migrations"),"\uff0c\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),Object(i.b)("img",{src:Object(o.a)("img/getstart4.png")}),Object(i.b)("p",null,Object(i.b)("strong",{parentName:"p"},"\u8f93\u5165\u4ee5\u4e0b\u547d\u4ee4"),"\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{}),"Add-Migration v0.0.1\n")),Object(i.b)("img",{src:Object(o.a)("img/getstart5.png")}),Object(i.b)("p",null,Object(i.b)("strong",{parentName:"p"},"\u63d0\u4ea4\u5230\u6570\u636e\u5e93\u66f4\u6539")),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{}),"Update-Database\n")),Object(i.b)("img",{src:Object(o.a)("img/getstart6.png")}),Object(i.b)("img",{src:Object(o.a)("img/getstart7.png"),style:{height:400}}),Object(i.b)("h2",{id:"23-\u589e\u5220\u67e5\u6539\u5206\u9875\u4f8b\u5b50"},"2.3 \u589e\u5220\u67e5\u6539\u5206\u9875\u4f8b\u5b50"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs",metastring:"{14-19}","{14-19}":!0}),'using Fur.Core;\nusing Fur.DatabaseAccessor;\nusing Fur.DynamicApiController;\nusing Mapster;\nusing Microsoft.EntityFrameworkCore;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\n\nnamespace Fur.Application\n{\n [DynamicApiController] // \u8fd9\u91cc\u4f7f\u7528\u7279\u6027\u65b9\u5f0f\n public class FurService /*: IDynamicApiController*/ // \u4e5f\u53ef\u4ee5\u4f7f\u7528\u63a5\u53e3\u65b9\u5f0f\n {\n // \u521d\u59cb\u5316\u4ed3\u50a8\n private readonly IRepository _personRepository;\n public FurService(IRepository personRepository)\n {\n _personRepository = personRepository;\n }\n\n /// \n /// \u65b0\u589e\u4e00\u6761\n /// \n public async Task Insert(PersonDto personDto)\n {\n // \u5982\u679c\u4e0d\u9700\u8981\u8fd4\u56de\u81ea\u589eId\uff0c\u4f7f\u7528 InsertAsync\u5373\u53ef\n var newEntity = await _personRepository.InsertNowAsync(personDto.Adapt());\n return newEntity.Entity.Id;\n\n // \u8fd8\u53ef\u4ee5\u76f4\u63a5\u64cd\u4f5c\n // await personDto.Adapt().InsertNowAsync();\n }\n\n /// \n /// \u66f4\u65b0\u4e00\u6761\n /// \n /// \n public async Task Update(PersonDto personDto)\n {\n await _personRepository.UpdateAsync(personDto.Adapt());\n\n // \u8fd8\u53ef\u4ee5\u76f4\u63a5\u64cd\u4f5c\n // await personDto.Adapt().UpdateAsync();\n }\n\n /// \n /// \u5220\u9664\u4e00\u6761\n /// \n /// \n public async Task Delete(int id)\n {\n await _personRepository.DeleteAsync(id);\n }\n\n /// \n /// \u67e5\u8be2\u4e00\u6761\n /// \n /// \n public async Task Find(int id)\n {\n var person = await _personRepository.FindAsync(id);\n return person.Adapt();\n }\n\n /// \n /// \u67e5\u8be2\u6240\u6709\n /// \n /// \n public async Task> GetAll()\n {\n var persons = await _personRepository.AsAsyncEnumerable();\n return persons.Adapt>();\n }\n\n /// \n /// \u5206\u9875\u67e5\u8be2\n /// \n /// \n /// \n /// \n public async Task> GetAllByPage(int pageIndex = 1, int pageSize = 10)\n {\n var pageResult = await _personRepository.AsQueryable().ToPagedListAsync(pageIndex, pageSize);\n return pageResult.Adapt>();\n }\n }\n}\n')),Object(i.b)("img",{src:Object(o.a)("img/getstart8.gif")}),Object(i.b)("h3",{id:"\u9644\u4e0a-persondto"},"\u9644\u4e0a ",Object(i.b)("inlineCode",{parentName:"h3"},"PersonDto")),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs"}),"using System.ComponentModel.DataAnnotations;\n\nnamespace Fur.Application\n{\n public class PersonDto\n {\n /// \n /// Id\n /// \n public int? Id { get; set; }\n\n /// \n /// \u59d3\u540d\n /// \n [StringLength(32, MinimumLength = 2)]\n public string Name { get; set; }\n\n /// \n /// \u5e74\u9f84\n /// \n public int Age { get; set; }\n }\n}\n")),Object(i.b)("p",null,"\u8bf4\u597d\u4e00\u5206\u949f\u5165\u95e8\uff0c\u4f60\u4eec\u7528\u4e86\u591a\u957f\u65f6\u95f4\u3002\ud83d\ude01"))}b.isMDXComponent=!0},138:function(e,n,t){"use strict";t.d(n,"a",(function(){return b})),t.d(n,"b",(function(){return d}));var r=t(0),a=t.n(r);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 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 p=a.a.createContext({}),u=function(e){var n=a.a.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},b=function(e){var n=u(e.components);return a.a.createElement(p.Provider,{value:n},e.children)},l={inlineCode:"code",wrapper:function(e){var n=e.children;return a.a.createElement(a.a.Fragment,{},n)}},m=a.a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,i=e.originalType,o=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),b=u(t),m=r,d=b["".concat(o,".").concat(m)]||b[m]||l[m]||i;return t?a.a.createElement(d,s(s({ref:n},p),{},{components:t})):a.a.createElement(d,s({ref:n},p))}));function d(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var i=t.length,o=new Array(i);o[0]=m;var s={};for(var c in n)hasOwnProperty.call(n,c)&&(s[c]=n[c]);s.originalType=e,s.mdxType="string"==typeof e?e:r,o[1]=s;for(var p=2;pfunction(e,n,t,{forcePrependBaseUrl:r=!1,absolute:i=!1}={}){if(!t)return t;if(t.startsWith("#"))return t;if(Object(a.b)(t))return t;if(r)return n+t;const o=t.startsWith(n)?t:n+t.replace(/^\//,"");return i?e+o:o}(n,e,t,r)}}function o(e,n={}){const{withBaseUrl:t}=i();return t(e,n)}},141:function(e,n,t){"use strict";function r(e){return!0===/^(\w*:|\/\/)/.test(e)}function a(e){return void 0!==e&&!r(e)}t.d(n,"b",(function(){return r})),t.d(n,"a",(function(){return a}))}}]); \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index 1e969ca9e5b..1ca8818e045 100644 --- a/docs/index.html +++ b/docs/index.html @@ -6,7 +6,7 @@ Fur 是 .NET 5 平台下极易入门、极速开发的 Web 应用框架。 Fur | Fur - + @@ -22,7 +22,7 @@

    Fur 是 .NET 5 平台下极易入门、极速开发的 Web 应用框架。

    [object Object]

    .NET 5 新起点

    .NET 5 是 .NET 的重要且令人兴奋的新方向。你会看到 .NET 变得更加简单,但也有更广泛的功能和实用程序。所有新的开发和功能都将是 .NET 5 的一部分,包括新的 C# 版本

    [object Object]

    “六级” 架构

    Fur 在设计之初就秉承着 “六极” :极易入门、极速开发、极少依赖、极少配置、极其灵活、极易维护 的设计思想,在架构设计上做了大量的优化,支持各个能力阶层技术员极速上手。

    [object Object]

    冲一杯咖啡的时间

    Fur 除了独具创新的设计理念和灵活的架构设计以外,同时还结合了主流的敏捷开发模式打造的一款极速开发框架。只需冲制一杯咖啡的时间便可完成工作

    - + diff --git a/docs/runtime~main.6df32296.js b/docs/runtime~main.a44330c3.js similarity index 93% rename from docs/runtime~main.6df32296.js rename to docs/runtime~main.a44330c3.js index 3da092a2fb6..0ac7b0ffca3 100644 --- a/docs/runtime~main.6df32296.js +++ b/docs/runtime~main.a44330c3.js @@ -1 +1 @@ -!function(e){function c(c){for(var d,r,t=c[0],n=c[1],o=c[2],u=0,l=[];u [SkipScan, AttributeUsage(AttributeTargets.Class)] - public class StartupAttribute : Attribute + public class AppStartupAttribute : Attribute { /// /// 构造函数 /// /// - public StartupAttribute(int order) + public AppStartupAttribute(int order) { Order = order; } @@ -35,10 +35,5 @@ public StartupAttribute(int order) /// 排序 /// public int Order { get; set; } - - /// - /// 服务列表 - /// - public string[] Services { get; set; } } } \ No newline at end of file diff --git a/framework/Fur/App/Extensions/AppServiceCollectionExtensions.cs b/framework/Fur/App/Extensions/AppServiceCollectionExtensions.cs index fe4bf6fc55c..39abd75e8e8 100644 --- a/framework/Fur/App/Extensions/AppServiceCollectionExtensions.cs +++ b/framework/Fur/App/Extensions/AppServiceCollectionExtensions.cs @@ -118,9 +118,9 @@ internal static IServiceCollection AddStartup(this IServiceCollection services, /// int private static int GetOrder(Type type) { - return !type.IsDefined(typeof(StartupAttribute), true) + return !type.IsDefined(typeof(AppStartupAttribute), true) ? 0 - : type.GetCustomAttribute(true).Order; + : type.GetCustomAttribute(true).Order; } } } \ No newline at end of file diff --git a/framework/Fur/FurStartup.cs b/framework/Fur/FurStartup.cs index 2456acb4da8..18002579779 100644 --- a/framework/Fur/FurStartup.cs +++ b/framework/Fur/FurStartup.cs @@ -13,7 +13,7 @@ namespace Fur { - [Startup(1000)] + [AppStartup(1000)] public sealed class FurStartup : AppStartup { } diff --git a/handbook/build/1ea356f4.cbd9b1c3.js b/handbook/build/1ea356f4.cbd9b1c3.js deleted file mode 100644 index 641a0243272..00000000000 --- a/handbook/build/1ea356f4.cbd9b1c3.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[14],{138:function(e,n,t){"use strict";t.d(n,"a",(function(){return d})),t.d(n,"b",(function(){return m}));var a=t(0),i=t.n(a);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 c(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 s=i.a.createContext({}),l=function(e){var n=i.a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):c(c({},n),e)),t},d=function(e){var n=l(e.components);return i.a.createElement(s.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return i.a.createElement(i.a.Fragment,{},n)}},u=i.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,r=e.originalType,o=e.parentName,s=b(e,["components","mdxType","originalType","parentName"]),d=l(t),u=a,m=d["".concat(o,".").concat(u)]||d[u]||p[u]||r;return t?i.a.createElement(m,c(c({ref:n},s),{},{components:t})):i.a.createElement(m,c({ref:n},s))}));function m(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var r=t.length,o=new Array(r);o[0]=u;var c={};for(var b in n)hasOwnProperty.call(n,b)&&(c[b]=n[b]);c.originalType=e,c.mdxType="string"==typeof e?e:a,o[1]=c;for(var s=2;sfunction(e,n,t,{forcePrependBaseUrl:a=!1,absolute:r=!1}={}){if(!t)return t;if(t.startsWith("#"))return t;if(Object(i.b)(t))return t;if(a)return n+t;const o=t.startsWith(n)?t:n+t.replace(/^\//,"");return r?e+o:o}(n,e,t,a)}}function o(e,n={}){const{withBaseUrl:t}=r();return t(e,n)}},141:function(e,n,t){"use strict";function a(e){return!0===/^(\w*:|\/\/)/.test(e)}function i(e){return void 0!==e&&!a(e)}t.d(n,"b",(function(){return a})),t.d(n,"a",(function(){return i}))},69:function(e,n,t){"use strict";t.r(n),t.d(n,"frontMatter",(function(){return c})),t.d(n,"metadata",(function(){return b})),t.d(n,"rightToc",(function(){return s})),t.d(n,"default",(function(){return d}));var a=t(2),i=t(6),r=(t(0),t(138)),o=t(140),c={id:"saas",title:"10. SaaS \u591a\u79df\u6237",sidebar_label:"10. SaaS \u591a\u79df\u6237"},b={unversionedId:"saas",id:"saas",isDocsHomePage:!1,title:"10. SaaS \u591a\u79df\u6237",description:"10.1 \u4ec0\u4e48\u662f SaaS",source:"@site/docs\\saas.mdx",slug:"/saas",permalink:"/fur/docs/saas",editUrl:"https://gitee.com/monksoul/Fur/tree/main/handbook/docs/saas.mdx",version:"current",sidebar_label:"10. SaaS \u591a\u79df\u6237",sidebar:"docs",previous:{title:"9.27 \u5206\u8868\u5206\u5e93",permalink:"/fur/docs/split-db"},next:{title:"11. \u4f9d\u8d56\u6ce8\u5165/\u63a7\u5236\u53cd\u8f6c",permalink:"/fur/docs/dependency-injection"}},s=[{value:"10.1 \u4ec0\u4e48\u662f SaaS",id:"101-\u4ec0\u4e48\u662f-saas",children:[]},{value:"10.2 \u4ec0\u4e48\u662f\u591a\u79df\u6237",id:"102-\u4ec0\u4e48\u662f\u591a\u79df\u6237",children:[]},{value:"10.3 \u5b9e\u73b0\u591a\u79df\u6237\u65b9\u6848",id:"103-\u5b9e\u73b0\u591a\u79df\u6237\u65b9\u6848",children:[{value:"10.3.1 \u72ec\u7acb\u6570\u636e\u5e93",id:"1031-\u72ec\u7acb\u6570\u636e\u5e93",children:[]},{value:"10.3.2 \u5171\u4eab\u6570\u636e\u5e93\uff0c\u72ec\u7acb Schema",id:"1032-\u5171\u4eab\u6570\u636e\u5e93\uff0c\u72ec\u7acb-schema",children:[]},{value:"10.3.3 \u5171\u4eab\u6570\u636e\u5e93\uff0c\u5171\u4eab Schema",id:"1033-\u5171\u4eab\u6570\u636e\u5e93\uff0c\u5171\u4eab-schema",children:[]}]},{value:"10.4 \u591a\u79df\u6237\u4f7f\u7528\u65b9\u6848",id:"104-\u591a\u79df\u6237\u4f7f\u7528\u65b9\u6848",children:[]},{value:"10.5 \u57fa\u4e8e TenantId \u7684\u65b9\u5f0f",id:"105-\u57fa\u4e8e-tenantid-\u7684\u65b9\u5f0f",children:[{value:"10.5.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1051-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.5.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1052-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.5.3 \u6dfb\u52a0 Tenant \u79cd\u5b50\u6570\u636e",id:"1053-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e",children:[]},{value:"10.5.4 \u6839\u636e\u6a21\u578b\u521b\u5efa Tenant \u8868",id:"1054-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868",children:[]},{value:"10.5.5 \u5b9e\u73b0 IMultiTenantOnTable \u63a5\u53e3",id:"1055-\u5b9e\u73b0-imultitenantontable-\u63a5\u53e3",children:[]},{value:"10.5.6 \u5b9e\u73b0 IModelBuilderFilter \u63a5\u53e3",id:"1056-\u5b9e\u73b0-imodelbuilderfilter-\u63a5\u53e3",children:[]},{value:"10.5.7 \u91cd\u5199 SavingChangesEvent \u4e8b\u4ef6\u65b9\u6cd5",id:"1057-\u91cd\u5199-savingchangesevent-\u4e8b\u4ef6\u65b9\u6cd5",children:[]}]},{value:"10.6 \u57fa\u4e8e Database \u7684\u65b9\u5f0f",id:"106-\u57fa\u4e8e-database-\u7684\u65b9\u5f0f",children:[{value:"10.6.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1061-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.6.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1062-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.6.3 \u6dfb\u52a0 Tenant \u79cd\u5b50\u6570\u636e",id:"1063-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e",children:[]},{value:"10.6.4 \u6839\u636e\u6a21\u578b\u521b\u5efa Tenant \u8868",id:"1064-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868",children:[]},{value:"10.6.5 \u5b9e\u73b0 IMultiTenantOnDatabase \u63a5\u53e3",id:"1065-\u5b9e\u73b0-imultitenantondatabase-\u63a5\u53e3",children:[]},{value:"10.6.6 \u91cd\u5199 OnConfiguring \u65b9\u6cd5",id:"1066-\u91cd\u5199-onconfiguring-\u65b9\u6cd5",children:[]}]},{value:"10.7 \u57fa\u4e8e Schema \u7684\u65b9\u5f0f",id:"107-\u57fa\u4e8e-schema-\u7684\u65b9\u5f0f",children:[{value:"10.7.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1071-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.7.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1072-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.7.3 \u6dfb\u52a0 Tenant \u79cd\u5b50\u6570\u636e",id:"1073-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e",children:[]},{value:"10.7.4 \u6839\u636e\u6a21\u578b\u521b\u5efa Tenant \u8868",id:"1074-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868",children:[]},{value:"10.7.5 \u5b9e\u73b0 IMultiTenantOnSchema \u63a5\u53e3",id:"1075-\u5b9e\u73b0-imultitenantonschema-\u63a5\u53e3",children:[]},{value:"10.7.6 \u5173\u4e8e Code First \u6570\u636e\u8fc1\u79fb",id:"1076-\u5173\u4e8e-code-first-\u6570\u636e\u8fc1\u79fb",children:[]}]},{value:"10.8 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"108-\u53cd\u9988\u4e0e\u5efa\u8bae",children:[]}],l={rightToc:s};function d(e){var n=e.components,t=Object(i.a)(e,["components"]);return Object(r.b)("wrapper",Object(a.a)({},l,t,{components:n,mdxType:"MDXLayout"}),Object(r.b)("h2",{id:"101-\u4ec0\u4e48\u662f-saas"},"10.1 \u4ec0\u4e48\u662f ",Object(r.b)("inlineCode",{parentName:"h2"},"SaaS")),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"SaaS \u662f Software-as-a-Service\uff08\u8f6f\u4ef6\u5373\u670d\u52a1\uff09\u7684\u7b80\u79f0\uff0c\u968f\u7740\u4e92\u8054\u7f51\u6280\u672f\u7684\u53d1\u5c55\u548c\u5e94\u7528\u8f6f\u4ef6\u7684\u6210\u719f\uff0c \u5728 21 \u4e16\u7eaa\u5f00\u59cb\u5174\u8d77\u7684\u4e00\u79cd\u5b8c\u5168\u521b\u65b0\u7684\u8f6f\u4ef6\u5e94\u7528\u6a21\u5f0f\u3002\u5b83\u4e0e\u201con-demand software\u201d\uff0cthe application service provider(ASP\uff0c\u5e94\u7528\u670d\u52a1\u63d0\u4f9b\u5546)\uff0chosted software(\u6258\u7ba1\u8f6f\u4ef6)\u6240\u5177\u6709\u76f8\u4f3c\u7684\u542b\u4e49\u3002"),Object(r.b)("p",{parentName:"blockquote"},"\u5b83\u662f\u4e00\u79cd\u901a\u8fc7 Internet \u63d0\u4f9b\u8f6f\u4ef6\u7684\u6a21\u5f0f\uff0c\u5382\u5546\u5c06\u5e94\u7528\u8f6f\u4ef6\u7edf\u4e00\u90e8\u7f72\u5728\u81ea\u5df1\u7684\u670d\u52a1\u5668\u4e0a\uff0c\u5ba2\u6237\u53ef\u4ee5\u6839\u636e\u81ea\u5df1\u5b9e\u9645\u9700\u6c42\uff0c\u901a\u8fc7\u4e92\u8054\u7f51\u5411\u5382\u5546\u5b9a\u8d2d\u6240\u9700\u7684\u5e94\u7528\u8f6f\u4ef6\u670d\u52a1\uff0c\u6309\u5b9a\u8d2d\u7684\u670d\u52a1\u591a\u5c11\u548c\u65f6\u95f4\u957f\u77ed\u5411\u5382\u5546\u652f\u4ed8\u8d39\u7528\uff0c\u5e76\u901a\u8fc7\u4e92\u8054\u7f51\u83b7\u5f97\u5382\u5546\u63d0\u4f9b\u7684\u670d\u52a1\u3002\u7528\u6237\u4e0d\u7528\u518d\u8d2d\u4e70\u8f6f\u4ef6\uff0c\u800c\u6539\u7528\u5411\u63d0\u4f9b\u5546\u79df\u7528\u57fa\u4e8e Web \u7684\u8f6f\u4ef6\uff0c\u6765\u7ba1\u7406\u4f01\u4e1a\u7ecf\u8425\u6d3b\u52a8\uff0c\u4e14\u65e0\u9700\u5bf9\u8f6f\u4ef6\u8fdb\u884c\u7ef4\u62a4\uff0c\u670d\u52a1\u63d0\u4f9b\u5546\u4f1a\u5168\u6743\u7ba1\u7406\u548c\u7ef4\u62a4\u8f6f\u4ef6\uff0c\u8f6f\u4ef6\u5382\u5546\u5728\u5411\u5ba2\u6237\u63d0\u4f9b\u4e92\u8054\u7f51\u5e94\u7528\u7684\u540c\u65f6\uff0c\u4e5f\u63d0\u4f9b\u8f6f\u4ef6\u7684\u79bb\u7ebf\u64cd\u4f5c\u548c\u672c\u5730\u6570\u636e\u5b58\u50a8\uff0c\u8ba9\u7528\u6237\u968f\u65f6\u968f\u5730\u90fd\u53ef\u4ee5\u4f7f\u7528\u5176\u5b9a\u8d2d\u7684\u8f6f\u4ef6\u548c\u670d\u52a1\u3002"),Object(r.b)("p",{parentName:"blockquote"},"\u5bf9\u4e8e\u8bb8\u591a\u5c0f\u578b\u4f01\u4e1a\u6765\u8bf4\uff0cSaaS \u662f\u91c7\u7528\u5148\u8fdb\u6280\u672f\u7684\u6700\u597d\u9014\u5f84\uff0c\u5b83\u6d88\u9664\u4e86\u4f01\u4e1a\u8d2d\u4e70\u3001\u6784\u5efa\u548c\u7ef4\u62a4\u57fa\u7840\u8bbe\u65bd\u548c\u5e94\u7528\u7a0b\u5e8f\u7684\u9700\u8981\u3002")),Object(r.b)("h2",{id:"102-\u4ec0\u4e48\u662f\u591a\u79df\u6237"},"10.2 \u4ec0\u4e48\u662f\u591a\u79df\u6237"),Object(r.b)("p",null,"\u591a\u79df\u6237\u6280\u672f\u6216\u79f0\u591a\u91cd\u79df\u8d41\u6280\u672f\uff0c\u7b80\u79f0 ",Object(r.b)("inlineCode",{parentName:"p"},"SaaS"),"\uff0c\u662f\u4e00\u79cd\u8f6f\u4ef6\u67b6\u6784\u6280\u672f\uff0c\u662f\u5b9e\u73b0\u5982\u4f55\u5728\u591a\u7528\u6237\u73af\u5883\u4e0b\uff08\u6b64\u5904\u7684\u591a\u7528\u6237\u4e00\u822c\u662f\u9762\u5411\u4f01\u4e1a\u7528\u6237\uff09\u5171\u7528\u76f8\u540c\u7684\u7cfb\u7edf\u6216\u7a0b\u5e8f\u7ec4\u4ef6\uff0c\u5e76\u4e14\u53ef\u786e\u4fdd\u5404\u7528\u6237\u95f4\u6570\u636e\u7684\u9694\u79bb\u6027\u3002"),Object(r.b)("p",null,Object(r.b)("strong",{parentName:"p"},"\u7b80\u5355\u8bb2\uff1a\u5728\u4e00\u53f0\u670d\u52a1\u5668\u4e0a\u8fd0\u884c\u5355\u4e2a\u5e94\u7528\u5b9e\u4f8b\uff0c\u5b83\u4e3a\u591a\u4e2a\u79df\u6237\uff08\u5ba2\u6237\uff09\u63d0\u4f9b\u670d\u52a1\u3002"),"\u4ece\u5b9a\u4e49\u4e2d\u6211\u4eec\u53ef\u4ee5\u7406\u89e3\uff1a\u591a\u79df\u6237\u662f\u4e00\u79cd\u67b6\u6784\uff0c\u76ee\u7684\u662f\u4e3a\u4e86\u8ba9\u591a\u7528\u6237\u73af\u5883\u4e0b\u4f7f\u7528\u540c\u4e00\u5957\u7a0b\u5e8f\uff0c\u4e14\u4fdd\u8bc1\u7528\u6237\u95f4\u6570\u636e\u9694\u79bb\u3002\u90a3\u4e48\u91cd\u70b9\u5c31\u5f88\u6d45\u663e\u6613\u61c2\u4e86\uff0c\u591a\u79df\u6237\u7684\u91cd\u70b9\u5c31\u662f\u540c\u4e00\u5957\u7a0b\u5e8f\u4e0b\u5b9e\u73b0\u591a\u7528\u6237\u6570\u636e\u7684\u9694\u79bb\u3002"),Object(r.b)("h2",{id:"103-\u5b9e\u73b0\u591a\u79df\u6237\u65b9\u6848"},"10.3 \u5b9e\u73b0\u591a\u79df\u6237\u65b9\u6848"),Object(r.b)("h3",{id:"1031-\u72ec\u7acb\u6570\u636e\u5e93"},"10.3.1 \u72ec\u7acb\u6570\u636e\u5e93"),Object(r.b)("p",null,"\u8fd9\u662f\u7b2c\u4e00\u79cd\u65b9\u6848\uff0c\u5373\u4e00\u4e2a\u79df\u6237\u4e00\u4e2a\u6570\u636e\u5e93\uff0c\u8fd9\u79cd\u65b9\u6848\u7684\u7528\u6237\u6570\u636e\u9694\u79bb\u7ea7\u522b\u6700\u9ad8\uff0c\u5b89\u5168\u6027\u6700\u597d\uff0c\u4f46\u6210\u672c\u8f83\u9ad8\u3002"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u4f18\u70b9\uff1a"),"\n\u4e3a\u4e0d\u540c\u7684\u79df\u6237\u63d0\u4f9b\u72ec\u7acb\u7684\u6570\u636e\u5e93\uff0c\u6709\u52a9\u4e8e\u7b80\u5316\u6570\u636e\u6a21\u578b\u7684\u6269\u5c55\u8bbe\u8ba1\uff0c\u6ee1\u8db3\u4e0d\u540c\u79df\u6237\u7684\u72ec\u7279\u9700\u6c42\uff1b\u5982\u679c\u51fa\u73b0\u6545\u969c\uff0c\u6062\u590d\u6570\u636e\u6bd4\u8f83\u7b80\u5355\u3002")),Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u7f3a\u70b9\uff1a"),"\n\u589e\u591a\u4e86\u6570\u636e\u5e93\u7684\u5b89\u88c5\u6570\u91cf\uff0c\u968f\u4e4b\u5e26\u6765\u7ef4\u62a4\u6210\u672c\u548c\u8d2d\u7f6e\u6210\u672c\u7684\u589e\u52a0\u3002 \u8fd9\u79cd\u65b9\u6848\u4e0e\u4f20\u7edf\u7684\u4e00\u4e2a\u5ba2\u6237\u3001\u4e00\u5957\u6570\u636e\u3001\u4e00\u5957\u90e8\u7f72\u7c7b\u4f3c\uff0c\u5dee\u522b\u53ea\u5728\u4e8e\u8f6f\u4ef6\u7edf\u4e00\u90e8\u7f72\u5728\u8fd0\u8425\u5546\u90a3\u91cc\u3002\u5982\u679c\u9762\u5bf9\u7684\u662f\u94f6\u884c\u3001\u533b\u9662\u7b49\u9700\u8981\u975e\u5e38\u9ad8\u6570\u636e\u9694\u79bb\u7ea7\u522b\u7684\u79df\u6237\uff0c\u53ef\u4ee5\u9009\u62e9\u8fd9\u79cd\u6a21\u5f0f\uff0c\u63d0\u9ad8\u79df\u7528\u7684\u5b9a\u4ef7\u3002\u5982\u679c\u5b9a\u4ef7\u8f83\u4f4e\uff0c\u4ea7\u54c1\u8d70\u4f4e\u4ef7\u8def\u7ebf\uff0c\u8fd9\u79cd\u65b9\u6848\u4e00\u822c\u5bf9\u8fd0\u8425\u5546\u6765\u8bf4\u662f\u65e0\u6cd5\u627f\u53d7\u7684\u3002"))),Object(r.b)("h3",{id:"1032-\u5171\u4eab\u6570\u636e\u5e93\uff0c\u72ec\u7acb-schema"},"10.3.2 \u5171\u4eab\u6570\u636e\u5e93\uff0c\u72ec\u7acb ",Object(r.b)("inlineCode",{parentName:"h3"},"Schema")),Object(r.b)("p",null,"\u8fd9\u662f\u7b2c\u4e8c\u79cd\u65b9\u6848\uff0c\u5373\u591a\u4e2a\u6216\u6240\u6709\u79df\u6237\u5171\u4eab ",Object(r.b)("inlineCode",{parentName:"p"},"Database"),"\uff0c\u4f46\u662f\u6bcf\u4e2a\u79df\u6237\u4e00\u4e2a ",Object(r.b)("inlineCode",{parentName:"p"},"Schema"),"\uff08\u4e5f\u53ef\u53eb\u505a\u4e00\u4e2a user\uff09\u3002\u5e95\u5c42\u5e93\u6bd4\u5982\u662f\uff1a",Object(r.b)("inlineCode",{parentName:"p"},"SqlServer"),"\u3001",Object(r.b)("inlineCode",{parentName:"p"},"Oracle")," \u7b49\uff0c\u4e00\u4e2a\u6570\u636e\u5e93\u4e0b\u53ef\u4ee5\u6709\u591a\u4e2a ",Object(r.b)("inlineCode",{parentName:"p"},"Schema"),"\u3002"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u4f18\u70b9\uff1a"),"\n\u4e3a\u5b89\u5168\u6027\u8981\u6c42\u8f83\u9ad8\u7684\u79df\u6237\u63d0\u4f9b\u4e86\u4e00\u5b9a\u7a0b\u5ea6\u7684\u903b\u8f91\u6570\u636e\u9694\u79bb\uff0c\u5e76\u4e0d\u662f\u5b8c\u5168\u9694\u79bb\uff1b\u6bcf\u4e2a\u6570\u636e\u5e93\u53ef\u652f\u6301\u66f4\u591a\u7684\u79df\u6237\u6570\u91cf\u3002")),Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u7f3a\u70b9\uff1a"),"\n\u5982\u679c\u51fa\u73b0\u6545\u969c\uff0c\u6570\u636e\u6062\u590d\u6bd4\u8f83\u56f0\u96be\uff0c\u56e0\u4e3a\u6062\u590d\u6570\u636e\u5e93\u5c06\u7275\u6d89\u5230\u5176\u4ed6\u79df\u6237\u7684\u6570\u636e\uff1b \u5982\u679c\u9700\u8981\u8de8\u79df\u6237\u7edf\u8ba1\u6570\u636e\uff0c\u5b58\u5728\u4e00\u5b9a\u56f0\u96be\u3002"))),Object(r.b)("h3",{id:"1033-\u5171\u4eab\u6570\u636e\u5e93\uff0c\u5171\u4eab-schema"},"10.3.3 \u5171\u4eab\u6570\u636e\u5e93\uff0c\u5171\u4eab ",Object(r.b)("inlineCode",{parentName:"h3"},"Schema")),Object(r.b)("p",null,"\u5171\u4eab\u6570\u636e\u8868 \u8fd9\u662f\u7b2c\u4e09\u79cd\u65b9\u6848\uff0c\u5373\u79df\u6237\u5171\u4eab\u540c\u4e00\u4e2a ",Object(r.b)("inlineCode",{parentName:"p"},"Database"),"\u3001\u540c\u4e00\u4e2a ",Object(r.b)("inlineCode",{parentName:"p"},"Schema"),"\uff0c\u4f46\u5728\u8868\u4e2d\u589e\u52a0 ",Object(r.b)("strong",{parentName:"p"},Object(r.b)("inlineCode",{parentName:"strong"},"TenantId"))," \u591a\u79df\u6237\u7684\u6570\u636e\u5b57\u6bb5\u3002\u8fd9\u662f\u5171\u4eab\u7a0b\u5ea6\u6700\u9ad8\u3001\u9694\u79bb\u7ea7\u522b\u6700\u4f4e\u7684\u6a21\u5f0f\u3002 \u5373\u6bcf\u63d2\u5165\u4e00\u6761\u6570\u636e\u65f6\u90fd\u9700\u8981\u6709\u4e00\u4e2a\u5ba2\u6237\u7684\u6807\u8bc6\u3002\u8fd9\u6837\u624d\u80fd\u5728\u540c\u4e00\u5f20\u8868\u4e2d\u533a\u5206\u51fa\u4e0d\u540c\u5ba2\u6237\u7684\u6570\u636e\u3002"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u4f18\u70b9\uff1a"),"\n\u4e09\u79cd\u65b9\u6848\u6bd4\u8f83\uff0c\u7b2c\u4e09\u79cd\u65b9\u6848\u7684\u7ef4\u62a4\u548c\u8d2d\u7f6e\u6210\u672c\u6700\u4f4e\uff0c\u5141\u8bb8\u6bcf\u4e2a\u6570\u636e\u5e93\u652f\u6301\u7684\u79df\u6237\u6570\u91cf\u6700\u591a\u3002")),Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u7f3a\u70b9\uff1a"),"\n\u9694\u79bb\u7ea7\u522b\u6700\u4f4e\uff0c\u5b89\u5168\u6027\u6700\u4f4e\uff0c\u9700\u8981\u5728\u8bbe\u8ba1\u5f00\u53d1\u65f6\u52a0\u5927\u5bf9\u5b89\u5168\u7684\u5f00\u53d1\u91cf\uff1b \u6570\u636e\u5907\u4efd\u548c\u6062\u590d\u6700\u56f0\u96be\uff0c\u9700\u8981\u9010\u8868\u9010\u6761\u5907\u4efd\u548c\u8fd8\u539f\u3002"))),Object(r.b)("h2",{id:"104-\u591a\u79df\u6237\u4f7f\u7528\u65b9\u6848"},"10.4 \u591a\u79df\u6237\u4f7f\u7528\u65b9\u6848"),Object(r.b)("p",null,Object(r.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u652f\u6301\u4ee5\u4e0a\u4e09\u79cd\u591a\u79df\u6237\u5b9e\u73b0\u65b9\u6848\uff0c\u4f7f\u7528\u7b80\u5355\u4e14\u5bb9\u6613\u7ef4\u62a4\u3002\u4e0b\u9762\u5206\u522b\u4f7f\u7528\u4e09\u79cd\u4e0d\u540c\u65b9\u5f0f\u6f14\u793a\u591a\u79df\u6237\u65b9\u6848\u7528\u6cd5\u3002"),Object(r.b)("h2",{id:"105-\u57fa\u4e8e-tenantid-\u7684\u65b9\u5f0f"},"10.5 \u57fa\u4e8e ",Object(r.b)("inlineCode",{parentName:"h2"},"TenantId")," \u7684\u65b9\u5f0f"),Object(r.b)("p",null,"\u6b64\u65b9\u5f0f\u5728\u4e2d\u5c0f\u578b\u4f01\u4e1a\u7cfb\u7edf\u4e2d\u6700\u4e3a\u5e38\u7528\uff0c\u7ef4\u62a4\u6210\u672c\u4f4e\uff0c\u8d2d\u7f6e\u6210\u672c\u4f4e\u3002"),Object(r.b)("h3",{id:"1051-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.5.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{6-7} title="Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"',"{6-7}":!0,title:'"Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class MultiTenantDbContext : AppDbContext\n {\n public MultiTenantDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-important alert alert--info"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u591a\u79df\u6237\u64cd\u4f5c\u5efa\u8bae\u5355\u72ec\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u800c\u4e14\u9700\u6307\u5b9a ",Object(r.b)("inlineCode",{parentName:"p"},"MultiTenantDbContextLocator")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u3002"))),Object(r.b)("h3",{id:"1052-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.5.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{14}","{14}":!0}),"using Fur.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.EntityFramework.Core\n{\n [Startup(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 options.AddDbPool(DbProvider.Sqlite);\n });\n }\n }\n}\n")),Object(r.b)("h3",{id:"1053-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e"},"10.5.3 \u6dfb\u52a0 ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u79cd\u5b50\u6570\u636e"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{8,12-28} title="Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"',"{8,12-28}":!0,title:'"Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Fur.EntityFramework.Core\n{\n public class TenantSeedData : IEntitySeedData\n {\n public IEnumerable HasData(DbContext dbContext, Type dbContextLocator)\n {\n return new List\n {\n new Tenant\n {\n TenantId=Guid.Parse("383AFB88-F519-FFF8-B364-6D563BF3687F"),\n Name="\u9ed8\u8ba4\u79df\u6237",\n Host="localhost:44313",\n CreatedTime=DateTime.Parse("2020-10-06 20:19:07")\n },\n new Tenant\n {\n TenantId=Guid.Parse("C5798CB6-16D6-0F42-EB56-59C695353BC0"),\n Name="\u5176\u4ed6\u79df\u6237",\n Host="localhost:5000",\n CreatedTime=DateTime.Parse("2020-10-06 20:20:32")\n }\n };\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u8bf4\u660e")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u8be5\u6b65\u9aa4\u53ea\u5728 ",Object(r.b)("inlineCode",{parentName:"p"},"Code First")," \u65b9\u5f0f\u6267\u884c\uff0c",Object(r.b)("inlineCode",{parentName:"p"},"Database First")," \u65e0\u9700\u914d\u7f6e\u79cd\u5b50\u6570\u636e\u3002"))),Object(r.b)("h3",{id:"1054-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868"},"10.5.4 \u6839\u636e\u6a21\u578b\u521b\u5efa ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u8868"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Add-Migration add_tenant_table -Context MultiTenantDbContext\n")),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Update-Database -Context MultiTenantDbContext\n")),Object(r.b)("h3",{id:"1055-\u5b9e\u73b0-imultitenantontable-\u63a5\u53e3"},"10.5.5 \u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"h3"},"IMultiTenantOnTable")," \u63a5\u53e3"),Object(r.b)("p",null,"\u5728\u9700\u8981\u591a\u79df\u6237\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"p"},"IMultiTenantOnTable")," \u63a5\u53e3\uff0c\u5982\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{8,14-17}","{8,14-17}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing System;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class FurDbContext : AppDbContext, IMultiTenantOnTable, IModelBuilderFilter\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public Guid? GetTenantId()\n {\n return base.Tenant.TenantId;\n }\n }\n}\n')),Object(r.b)("p",null,"\u5728 ",Object(r.b)("inlineCode",{parentName:"p"},"GetTenantId()")," \u65b9\u6cd5\u4e2d\uff0c\u9996\u5148\u83b7\u53d6\u8bf7\u6c42\u7684 ",Object(r.b)("inlineCode",{parentName:"p"},"\u4e3b\u673a\u5730\u5740"),"\uff0c\u7136\u540e\u6839\u636e\u4e3b\u673a\u5730\u5740\u67e5\u8be2\u5bf9\u5e94\u7684\u79df\u6237 ",Object(r.b)("inlineCode",{parentName:"p"},"TenantIdId"),"\uff0c\u907f\u514d\u591a\u6b21\u67e5\u8be2\u6570\u636e\u5e93\uff0c\u8fd9\u91cc\u4f7f\u7528\u4e86 ",Object(r.b)("inlineCode",{parentName:"p"},"IMemoryCache")," \u5185\u5b58\u7f13\u5b58\u3002"),Object(r.b)("h3",{id:"1056-\u5b9e\u73b0-imodelbuilderfilter-\u63a5\u53e3"},"10.5.6 \u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"h3"},"IModelBuilderFilter")," \u63a5\u53e3"),Object(r.b)("p",null,Object(r.b)("inlineCode",{parentName:"p"},"IModelBuilderFilter")," \u63a5\u53e3\u662f\u5168\u5c40\u67e5\u8be2\u8fc7\u6ee4\u5668\u5b9e\u73b0\u63a5\u53e3\uff0c\u6240\u4ee5\u6211\u4eec\u9700\u8981\u914d\u7f6e\u5b9e\u4f53 ",Object(r.b)("inlineCode",{parentName:"p"},"TenantId")," \u8fc7\u6ee4\u5668"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{9,20-23}","{9,20-23}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class FurDbContext : AppDbContext, IMultiTenantOnTable, IModelBuilderFilter\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public Guid? GetTenantId()\n {\n return base.Tenant.TenantId;\n }\n\n public void OnCreating(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.HasQueryFilter(TenantIdQueryFilterExpression(entityBuilder, GetTenantId().Value));\n }\n }\n}\n')),Object(r.b)("h3",{id:"1057-\u91cd\u5199-savingchangesevent-\u4e8b\u4ef6\u65b9\u6cd5"},"10.5.7 \u91cd\u5199 ",Object(r.b)("inlineCode",{parentName:"h3"},"SavingChangesEvent")," \u4e8b\u4ef6\u65b9\u6cd5"),Object(r.b)("p",null,"\u901a\u8fc7\u4e0a\u9762\u7684\u6b65\u9aa4\uff0c\u6211\u4eec\u5df2\u7ecf\u89e3\u51b3\u4e86 ",Object(r.b)("inlineCode",{parentName:"p"},"\u67e5\u8be2")," \u79df\u6237\u8fc7\u6ee4\u529f\u80fd\uff0c\u4f46\u662f ",Object(r.b)("inlineCode",{parentName:"p"},"\u65b0\u589e")," \u548c ",Object(r.b)("inlineCode",{parentName:"p"},"\u66f4\u65b0")," \u8fd8\u672a\u5904\u7406\u3002"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"\u65b0\u589e")," \u6570\u636e\u7684\u65f6\u5019\u81ea\u52a8\u8bbe\u7f6e ",Object(r.b)("inlineCode",{parentName:"li"},"TenantId")," \u7684\u503c"),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"\u66f4\u65b0")," \u6570\u636e\u7684\u65f6\u5019\u6392\u9664 ",Object(r.b)("inlineCode",{parentName:"li"},"TenantId")," \u5c5e\u6027\u66f4\u65b0")),Object(r.b)("p",null,"\u5b9e\u73b0\u4e0a\u9762\u7684\u6b65\u9aa4\u5f88\u7b80\u5355\uff0c\u53ea\u9700\u8981\u91cd\u5199 ",Object(r.b)("inlineCode",{parentName:"p"},"SavingChangesEvent")," \u4e8b\u4ef6\u65b9\u6cd5\u5373\u53ef\u3002"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{26-48}","{26-48}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\nusing System.Linq;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class FurDbContext : AppDbContext, IMultiTenantOnTable, IModelBuilderFilter\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public Guid? GetTenantId()\n {\n return base.Tenant.TenantId;\n }\n\n public void OnCreating(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.HasQueryFilter(TenantIdQueryFilterExpression(entityBuilder, GetTenantId().Value));\n }\n\n protected override void SavingChangesEvent(object sender, SavingChangesEventArgs e)\n {\n // \u83b7\u53d6\u5f53\u524d\u4e8b\u4ef6\u5bf9\u5e94\u4e0a\u4e0b\u6587\n var dbContext = sender as FurDbContext;\n\n // \u83b7\u53d6\u6240\u6709\u65b0\u589e\u548c\u66f4\u65b0\u7684\u5b9e\u4f53\n var entities = dbContext.ChangeTracker.Entries().Where(u => u.State == EntityState.Added || u.State == EntityState.Modified);\n\n foreach (var entity in entities)\n {\n switch (entity.State)\n {\n // \u81ea\u52a8\u8bbe\u7f6e\u79df\u6237Id\n case EntityState.Added:\n entity.Property(nameof(Entity.TenantId)).CurrentValue = base.TenantId;\n break;\n // \u6392\u9664\u79df\u6237Id\n case EntityState.Modified:\n entity.Property(nameof(Entity.TenantId)).IsModified = false;\n break;\n }\n }\n }\n }\n}\n')),Object(r.b)("img",{src:Object(o.a)("img/saas1.png")}),Object(r.b)("h2",{id:"106-\u57fa\u4e8e-database-\u7684\u65b9\u5f0f"},"10.6 \u57fa\u4e8e ",Object(r.b)("inlineCode",{parentName:"h2"},"Database")," \u7684\u65b9\u5f0f"),Object(r.b)("p",null,"\u6b64\u65b9\u5f0f\u5728\u4e2d\u5927\u578b\u4f01\u4e1a\u7cfb\u7edf\u4e2d\u6700\u4e3a\u5e38\u7528\uff0c\u4e00\u4e2a\u79df\u6237\uff08\u5ba2\u6237\uff09\u4e00\u4e2a\u72ec\u7acb\u7684\u6570\u636e\u5e93\u3002"),Object(r.b)("h3",{id:"1061-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.6.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{6-7} title="Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"',"{6-7}":!0,title:'"Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class MultiTenantDbContext : AppDbContext\n {\n public MultiTenantDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-important alert alert--info"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u591a\u79df\u6237\u64cd\u4f5c\u5efa\u8bae\u5355\u72ec\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u800c\u4e14\u9700\u6307\u5b9a ",Object(r.b)("inlineCode",{parentName:"p"},"MultiTenantDbContextLocator")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u3002"))),Object(r.b)("h3",{id:"1062-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.6.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{13,14}","{13,14}":!0}),"using Fur.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.EntityFramework.Core\n{\n [Startup(600)]\n public sealed class FurEntityFrameworkCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddDatabaseAccessor(options =>\n {\n options.AddDb(DbProvider.Sqlite);\n options.AddDbPool(DbProvider.Sqlite);\n });\n }\n }\n}\n")),Object(r.b)("div",{className:"admonition admonition-caution alert alert--warning"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 16 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u9700\u8981 ",Object(r.b)("inlineCode",{parentName:"p"},"Database")," \u591a\u79df\u6237\u65b9\u6848\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u9700\u8981\u91c7\u7528 ",Object(r.b)("inlineCode",{parentName:"p"},"AddDb")," \u6ce8\u518c\uff0c\u800c\u4e0d\u662f ",Object(r.b)("inlineCode",{parentName:"p"},"AddDbPool"),"\u3002\u539f\u56e0\u662f ",Object(r.b)("inlineCode",{parentName:"p"},"AddDbPool")," \u65b9\u5f0f\u6ce8\u518c\u540e\u7eed\u4e0d\u652f\u6301 ",Object(r.b)("inlineCode",{parentName:"p"},"OnConfiguring")," \u91cd\u5199\uff01\uff01\uff01"))),Object(r.b)("h3",{id:"1063-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e"},"10.6.3 \u6dfb\u52a0 ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u79cd\u5b50\u6570\u636e"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{8,12-30} title="Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"',"{8,12-30}":!0,title:'"Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Fur.EntityFramework.Core\n{\n public class TenantSeedData : IEntitySeedData\n {\n public IEnumerable HasData(DbContext dbContext, Type dbContextLocator)\n {\n return new List\n {\n new Tenant\n {\n TenantId=Guid.Parse("383AFB88-F519-FFF8-B364-6D563BF3687F"),\n Name="\u9ed8\u8ba4\u79df\u6237",\n Host="localhost:44313",\n CreatedTime=DateTime.Parse("2020-10-06 20:19:07"),\n ConnectionString="Data Source=./Fur.db" // \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32\n },\n new Tenant\n {\n TenantId=Guid.Parse("C5798CB6-16D6-0F42-EB56-59C695353BC0"),\n Name="\u5176\u4ed6\u79df\u6237",\n Host="localhost:5000",\n CreatedTime=DateTime.Parse("2020-10-06 20:20:32"),\n ConnectionString="Data Source=./Fur2.db" // \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32\n }\n };\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u8bf4\u660e")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u8be5\u6b65\u9aa4\u53ea\u5728 ",Object(r.b)("inlineCode",{parentName:"p"},"Code First")," \u65b9\u5f0f\u6267\u884c\uff0c",Object(r.b)("inlineCode",{parentName:"p"},"Database First")," \u65e0\u9700\u914d\u7f6e\u79cd\u5b50\u6570\u636e\u3002"))),Object(r.b)("h3",{id:"1064-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868"},"10.6.4 \u6839\u636e\u6a21\u578b\u521b\u5efa ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u8868"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Add-Migration add_tenant_table -Context MultiTenantDbContext\n")),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Update-Database -Context MultiTenantDbContext\n")),Object(r.b)("h3",{id:"1065-\u5b9e\u73b0-imultitenantondatabase-\u63a5\u53e3"},"10.6.5 \u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"h3"},"IMultiTenantOnDatabase")," \u63a5\u53e3"),Object(r.b)("p",null,"\u5728\u9700\u8981\u591a\u79df\u6237\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"p"},"IMultiTenantOnDatabase")," \u63a5\u53e3\uff0c\u5982\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{6,12-15}","{6,12-15}":!0}),"using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n public class FurDbContext : AppDbContext, IMultiTenantOnDatabase\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public string GetDatabaseConnectionString()\n {\n return base.Tenant.ConnectionString;\n }\n }\n}\n")),Object(r.b)("h3",{id:"1066-\u91cd\u5199-onconfiguring-\u65b9\u6cd5"},"10.6.6 \u91cd\u5199 ",Object(r.b)("inlineCode",{parentName:"h3"},"OnConfiguring")," \u65b9\u6cd5"),Object(r.b)("p",null,"\u5728\u9700\u8981\u591a\u79df\u6237\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u91cd\u5199 ",Object(r.b)("inlineCode",{parentName:"p"},"OnConfiguring")," \u65b9\u6cd5\u5e76\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{12-17}","{12-17}":!0}),"using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n public class FurDbContext : AppDbContext, IMultiTenantOnDatabase\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)\n {\n optionsBuilder.UseSqlite(GetDatabaseConnectionString());\n\n base.OnConfiguring(optionsBuilder);\n }\n\n public string GetDatabaseConnectionString()\n {\n return base.Tenant.ConnectionString;\n }\n }\n}\n")),Object(r.b)("img",{src:Object(o.a)("img/saas2.png")}),Object(r.b)("h2",{id:"107-\u57fa\u4e8e-schema-\u7684\u65b9\u5f0f"},"10.7 \u57fa\u4e8e ",Object(r.b)("inlineCode",{parentName:"h2"},"Schema")," \u7684\u65b9\u5f0f"),Object(r.b)("p",null,"\u6b64\u65b9\u5f0f\u5728\u4e2d\u5c0f\u578b\u4f01\u4e1a\u7cfb\u7edf\u4e2d\u4e5f\u4e0d\u5c11\u89c1\uff0c\u4e00\u4e2a\u79df\u6237\uff08\u5ba2\u6237\uff09\u5171\u4eab\u6570\u636e\u5e93\u4e14\u4e0d\u540c ",Object(r.b)("inlineCode",{parentName:"p"},"Schema"),"\u3002"),Object(r.b)("h3",{id:"1071-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.7.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{6-7} title="Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"',"{6-7}":!0,title:'"Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class MultiTenantDbContext : AppDbContext\n {\n public MultiTenantDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-important alert alert--info"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u591a\u79df\u6237\u64cd\u4f5c\u5efa\u8bae\u5355\u72ec\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u800c\u4e14\u9700\u6307\u5b9a ",Object(r.b)("inlineCode",{parentName:"p"},"MultiTenantDbContextLocator")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u3002"))),Object(r.b)("h3",{id:"1072-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.7.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{14}","{14}":!0}),"using Fur.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.EntityFramework.Core\n{\n [Startup(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 options.AddDbPool(DbProvider.Sqlite);\n });\n }\n }\n}\n")),Object(r.b)("h3",{id:"1073-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e"},"10.7.3 \u6dfb\u52a0 ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u79cd\u5b50\u6570\u636e"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{8,12-30} title="Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"',"{8,12-30}":!0,title:'"Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Fur.EntityFramework.Core\n{\n public class TenantSeedData : IEntitySeedData\n {\n public IEnumerable HasData(DbContext dbContext, Type dbContextLocator)\n {\n return new List\n {\n new Tenant\n {\n TenantId=Guid.Parse("383AFB88-F519-FFF8-B364-6D563BF3687F"),\n Name="\u9ed8\u8ba4\u79df\u6237",\n Host="localhost:44313",\n CreatedTime=DateTime.Parse("2020-10-06 20:19:07"),\n Schema="dbo" // Schema\n },\n new Tenant\n {\n TenantId=Guid.Parse("C5798CB6-16D6-0F42-EB56-59C695353BC0"),\n Name="\u5176\u4ed6\u79df\u6237",\n Host="localhost:5000",\n CreatedTime=DateTime.Parse("2020-10-06 20:20:32"),\n Schema="fur" // Schema\n }\n };\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u8bf4\u660e")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u8be5\u6b65\u9aa4\u53ea\u5728 ",Object(r.b)("inlineCode",{parentName:"p"},"Code First")," \u65b9\u5f0f\u6267\u884c\uff0c",Object(r.b)("inlineCode",{parentName:"p"},"Database First")," \u65e0\u9700\u914d\u7f6e\u79cd\u5b50\u6570\u636e\u3002"))),Object(r.b)("h3",{id:"1074-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868"},"10.7.4 \u6839\u636e\u6a21\u578b\u521b\u5efa ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u8868"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Add-Migration add_tenant_table -Context MultiTenantDbContext\n")),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Update-Database -Context MultiTenantDbContext\n")),Object(r.b)("h3",{id:"1075-\u5b9e\u73b0-imultitenantonschema-\u63a5\u53e3"},"10.7.5 \u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"h3"},"IMultiTenantOnSchema")," \u63a5\u53e3"),Object(r.b)("p",null,"\u5728\u9700\u8981\u591a\u79df\u6237\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"p"},"IMultiTenantOnSchema")," \u63a5\u53e3\uff0c\u5982\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{6,12-15}","{6,12-15}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class FurDbContext : AppDbContext, IMultiTenantOnSchema\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public string GetSchemaName()\n {\n return base.Tenant.Schema;\n }\n }\n}\n')),Object(r.b)("h3",{id:"1076-\u5173\u4e8e-code-first-\u6570\u636e\u8fc1\u79fb"},"10.7.6 \u5173\u4e8e ",Object(r.b)("inlineCode",{parentName:"h3"},"Code First \u6570\u636e\u8fc1\u79fb")),Object(r.b)("p",null,"\u57fa\u4e8e ",Object(r.b)("inlineCode",{parentName:"p"},"Schema")," \u65b9\u5f0f\u6bd4\u8f83\u7279\u522b\uff0c\u751f\u6210\u6570\u636e\u8fc1\u79fb\u7684\u65f6\u5019\u6ca1\u529e\u6cd5\u83b7\u53d6\u79df\u6237\u4fe1\u606f\uff0c\u6240\u4ee5\u5efa\u8bae",Object(r.b)("strong",{parentName:"p"},"\u5206\u5f00\u591a\u6b21\u8fc1\u79fb"),"\uff0c\u5982\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),'public string GetSchemaName()\n{\n return base.Tenant.Schema?? "\u79df\u6237\u4e00Schema";\n}\n')),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),'public string GetSchemaName()\n{\n return base.Tenant.Schema?? "\u79df\u6237\u4e8cSchema";\n}\n')),Object(r.b)("p",null,"\u8fd9\u6837\u5c31\u53ef\u4ee5\u5728\u8fc1\u79fb\u7684\u65f6\u5019\u751f\u6210\u591a\u6b21\u8fc1\u79fb\u4e86\u3002"),Object(r.b)("h2",{id:"108-\u53cd\u9988\u4e0e\u5efa\u8bae"},"10.8 \u53cd\u9988\u4e0e\u5efa\u8bae"),Object(r.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e0e\u6211\u4eec\u4ea4\u6d41")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u7ed9 Fur \u63d0 ",Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://gitee.com/monksoul/Fur/issues/new?issue"}),"Issue"),"\u3002"))))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/1ea356f4.cdf2ad5e.js b/handbook/build/1ea356f4.cdf2ad5e.js new file mode 100644 index 00000000000..8b5277198ae --- /dev/null +++ b/handbook/build/1ea356f4.cdf2ad5e.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[14],{138:function(e,n,t){"use strict";t.d(n,"a",(function(){return d})),t.d(n,"b",(function(){return m}));var a=t(0),i=t.n(a);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 c(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 s=i.a.createContext({}),l=function(e){var n=i.a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):c(c({},n),e)),t},d=function(e){var n=l(e.components);return i.a.createElement(s.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return i.a.createElement(i.a.Fragment,{},n)}},u=i.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,r=e.originalType,o=e.parentName,s=b(e,["components","mdxType","originalType","parentName"]),d=l(t),u=a,m=d["".concat(o,".").concat(u)]||d[u]||p[u]||r;return t?i.a.createElement(m,c(c({ref:n},s),{},{components:t})):i.a.createElement(m,c({ref:n},s))}));function m(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var r=t.length,o=new Array(r);o[0]=u;var c={};for(var b in n)hasOwnProperty.call(n,b)&&(c[b]=n[b]);c.originalType=e,c.mdxType="string"==typeof e?e:a,o[1]=c;for(var s=2;sfunction(e,n,t,{forcePrependBaseUrl:a=!1,absolute:r=!1}={}){if(!t)return t;if(t.startsWith("#"))return t;if(Object(i.b)(t))return t;if(a)return n+t;const o=t.startsWith(n)?t:n+t.replace(/^\//,"");return r?e+o:o}(n,e,t,a)}}function o(e,n={}){const{withBaseUrl:t}=r();return t(e,n)}},141:function(e,n,t){"use strict";function a(e){return!0===/^(\w*:|\/\/)/.test(e)}function i(e){return void 0!==e&&!a(e)}t.d(n,"b",(function(){return a})),t.d(n,"a",(function(){return i}))},69:function(e,n,t){"use strict";t.r(n),t.d(n,"frontMatter",(function(){return c})),t.d(n,"metadata",(function(){return b})),t.d(n,"rightToc",(function(){return s})),t.d(n,"default",(function(){return d}));var a=t(2),i=t(6),r=(t(0),t(138)),o=t(140),c={id:"saas",title:"10. SaaS \u591a\u79df\u6237",sidebar_label:"10. SaaS \u591a\u79df\u6237"},b={unversionedId:"saas",id:"saas",isDocsHomePage:!1,title:"10. SaaS \u591a\u79df\u6237",description:"10.1 \u4ec0\u4e48\u662f SaaS",source:"@site/docs\\saas.mdx",slug:"/saas",permalink:"/fur/docs/saas",editUrl:"https://gitee.com/monksoul/Fur/tree/main/handbook/docs/saas.mdx",version:"current",sidebar_label:"10. SaaS \u591a\u79df\u6237",sidebar:"docs",previous:{title:"9.27 \u5206\u8868\u5206\u5e93",permalink:"/fur/docs/split-db"},next:{title:"11. \u4f9d\u8d56\u6ce8\u5165/\u63a7\u5236\u53cd\u8f6c",permalink:"/fur/docs/dependency-injection"}},s=[{value:"10.1 \u4ec0\u4e48\u662f SaaS",id:"101-\u4ec0\u4e48\u662f-saas",children:[]},{value:"10.2 \u4ec0\u4e48\u662f\u591a\u79df\u6237",id:"102-\u4ec0\u4e48\u662f\u591a\u79df\u6237",children:[]},{value:"10.3 \u5b9e\u73b0\u591a\u79df\u6237\u65b9\u6848",id:"103-\u5b9e\u73b0\u591a\u79df\u6237\u65b9\u6848",children:[{value:"10.3.1 \u72ec\u7acb\u6570\u636e\u5e93",id:"1031-\u72ec\u7acb\u6570\u636e\u5e93",children:[]},{value:"10.3.2 \u5171\u4eab\u6570\u636e\u5e93\uff0c\u72ec\u7acb Schema",id:"1032-\u5171\u4eab\u6570\u636e\u5e93\uff0c\u72ec\u7acb-schema",children:[]},{value:"10.3.3 \u5171\u4eab\u6570\u636e\u5e93\uff0c\u5171\u4eab Schema",id:"1033-\u5171\u4eab\u6570\u636e\u5e93\uff0c\u5171\u4eab-schema",children:[]}]},{value:"10.4 \u591a\u79df\u6237\u4f7f\u7528\u65b9\u6848",id:"104-\u591a\u79df\u6237\u4f7f\u7528\u65b9\u6848",children:[]},{value:"10.5 \u57fa\u4e8e TenantId \u7684\u65b9\u5f0f",id:"105-\u57fa\u4e8e-tenantid-\u7684\u65b9\u5f0f",children:[{value:"10.5.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1051-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.5.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1052-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.5.3 \u6dfb\u52a0 Tenant \u79cd\u5b50\u6570\u636e",id:"1053-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e",children:[]},{value:"10.5.4 \u6839\u636e\u6a21\u578b\u521b\u5efa Tenant \u8868",id:"1054-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868",children:[]},{value:"10.5.5 \u5b9e\u73b0 IMultiTenantOnTable \u63a5\u53e3",id:"1055-\u5b9e\u73b0-imultitenantontable-\u63a5\u53e3",children:[]},{value:"10.5.6 \u5b9e\u73b0 IModelBuilderFilter \u63a5\u53e3",id:"1056-\u5b9e\u73b0-imodelbuilderfilter-\u63a5\u53e3",children:[]},{value:"10.5.7 \u91cd\u5199 SavingChangesEvent \u4e8b\u4ef6\u65b9\u6cd5",id:"1057-\u91cd\u5199-savingchangesevent-\u4e8b\u4ef6\u65b9\u6cd5",children:[]}]},{value:"10.6 \u57fa\u4e8e Database \u7684\u65b9\u5f0f",id:"106-\u57fa\u4e8e-database-\u7684\u65b9\u5f0f",children:[{value:"10.6.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1061-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.6.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1062-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.6.3 \u6dfb\u52a0 Tenant \u79cd\u5b50\u6570\u636e",id:"1063-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e",children:[]},{value:"10.6.4 \u6839\u636e\u6a21\u578b\u521b\u5efa Tenant \u8868",id:"1064-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868",children:[]},{value:"10.6.5 \u5b9e\u73b0 IMultiTenantOnDatabase \u63a5\u53e3",id:"1065-\u5b9e\u73b0-imultitenantondatabase-\u63a5\u53e3",children:[]},{value:"10.6.6 \u91cd\u5199 OnConfiguring \u65b9\u6cd5",id:"1066-\u91cd\u5199-onconfiguring-\u65b9\u6cd5",children:[]}]},{value:"10.7 \u57fa\u4e8e Schema \u7684\u65b9\u5f0f",id:"107-\u57fa\u4e8e-schema-\u7684\u65b9\u5f0f",children:[{value:"10.7.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1071-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.7.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"1072-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"10.7.3 \u6dfb\u52a0 Tenant \u79cd\u5b50\u6570\u636e",id:"1073-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e",children:[]},{value:"10.7.4 \u6839\u636e\u6a21\u578b\u521b\u5efa Tenant \u8868",id:"1074-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868",children:[]},{value:"10.7.5 \u5b9e\u73b0 IMultiTenantOnSchema \u63a5\u53e3",id:"1075-\u5b9e\u73b0-imultitenantonschema-\u63a5\u53e3",children:[]},{value:"10.7.6 \u5173\u4e8e Code First \u6570\u636e\u8fc1\u79fb",id:"1076-\u5173\u4e8e-code-first-\u6570\u636e\u8fc1\u79fb",children:[]}]},{value:"10.8 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"108-\u53cd\u9988\u4e0e\u5efa\u8bae",children:[]}],l={rightToc:s};function d(e){var n=e.components,t=Object(i.a)(e,["components"]);return Object(r.b)("wrapper",Object(a.a)({},l,t,{components:n,mdxType:"MDXLayout"}),Object(r.b)("h2",{id:"101-\u4ec0\u4e48\u662f-saas"},"10.1 \u4ec0\u4e48\u662f ",Object(r.b)("inlineCode",{parentName:"h2"},"SaaS")),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"SaaS \u662f Software-as-a-Service\uff08\u8f6f\u4ef6\u5373\u670d\u52a1\uff09\u7684\u7b80\u79f0\uff0c\u968f\u7740\u4e92\u8054\u7f51\u6280\u672f\u7684\u53d1\u5c55\u548c\u5e94\u7528\u8f6f\u4ef6\u7684\u6210\u719f\uff0c \u5728 21 \u4e16\u7eaa\u5f00\u59cb\u5174\u8d77\u7684\u4e00\u79cd\u5b8c\u5168\u521b\u65b0\u7684\u8f6f\u4ef6\u5e94\u7528\u6a21\u5f0f\u3002\u5b83\u4e0e\u201con-demand software\u201d\uff0cthe application service provider(ASP\uff0c\u5e94\u7528\u670d\u52a1\u63d0\u4f9b\u5546)\uff0chosted software(\u6258\u7ba1\u8f6f\u4ef6)\u6240\u5177\u6709\u76f8\u4f3c\u7684\u542b\u4e49\u3002"),Object(r.b)("p",{parentName:"blockquote"},"\u5b83\u662f\u4e00\u79cd\u901a\u8fc7 Internet \u63d0\u4f9b\u8f6f\u4ef6\u7684\u6a21\u5f0f\uff0c\u5382\u5546\u5c06\u5e94\u7528\u8f6f\u4ef6\u7edf\u4e00\u90e8\u7f72\u5728\u81ea\u5df1\u7684\u670d\u52a1\u5668\u4e0a\uff0c\u5ba2\u6237\u53ef\u4ee5\u6839\u636e\u81ea\u5df1\u5b9e\u9645\u9700\u6c42\uff0c\u901a\u8fc7\u4e92\u8054\u7f51\u5411\u5382\u5546\u5b9a\u8d2d\u6240\u9700\u7684\u5e94\u7528\u8f6f\u4ef6\u670d\u52a1\uff0c\u6309\u5b9a\u8d2d\u7684\u670d\u52a1\u591a\u5c11\u548c\u65f6\u95f4\u957f\u77ed\u5411\u5382\u5546\u652f\u4ed8\u8d39\u7528\uff0c\u5e76\u901a\u8fc7\u4e92\u8054\u7f51\u83b7\u5f97\u5382\u5546\u63d0\u4f9b\u7684\u670d\u52a1\u3002\u7528\u6237\u4e0d\u7528\u518d\u8d2d\u4e70\u8f6f\u4ef6\uff0c\u800c\u6539\u7528\u5411\u63d0\u4f9b\u5546\u79df\u7528\u57fa\u4e8e Web \u7684\u8f6f\u4ef6\uff0c\u6765\u7ba1\u7406\u4f01\u4e1a\u7ecf\u8425\u6d3b\u52a8\uff0c\u4e14\u65e0\u9700\u5bf9\u8f6f\u4ef6\u8fdb\u884c\u7ef4\u62a4\uff0c\u670d\u52a1\u63d0\u4f9b\u5546\u4f1a\u5168\u6743\u7ba1\u7406\u548c\u7ef4\u62a4\u8f6f\u4ef6\uff0c\u8f6f\u4ef6\u5382\u5546\u5728\u5411\u5ba2\u6237\u63d0\u4f9b\u4e92\u8054\u7f51\u5e94\u7528\u7684\u540c\u65f6\uff0c\u4e5f\u63d0\u4f9b\u8f6f\u4ef6\u7684\u79bb\u7ebf\u64cd\u4f5c\u548c\u672c\u5730\u6570\u636e\u5b58\u50a8\uff0c\u8ba9\u7528\u6237\u968f\u65f6\u968f\u5730\u90fd\u53ef\u4ee5\u4f7f\u7528\u5176\u5b9a\u8d2d\u7684\u8f6f\u4ef6\u548c\u670d\u52a1\u3002"),Object(r.b)("p",{parentName:"blockquote"},"\u5bf9\u4e8e\u8bb8\u591a\u5c0f\u578b\u4f01\u4e1a\u6765\u8bf4\uff0cSaaS \u662f\u91c7\u7528\u5148\u8fdb\u6280\u672f\u7684\u6700\u597d\u9014\u5f84\uff0c\u5b83\u6d88\u9664\u4e86\u4f01\u4e1a\u8d2d\u4e70\u3001\u6784\u5efa\u548c\u7ef4\u62a4\u57fa\u7840\u8bbe\u65bd\u548c\u5e94\u7528\u7a0b\u5e8f\u7684\u9700\u8981\u3002")),Object(r.b)("h2",{id:"102-\u4ec0\u4e48\u662f\u591a\u79df\u6237"},"10.2 \u4ec0\u4e48\u662f\u591a\u79df\u6237"),Object(r.b)("p",null,"\u591a\u79df\u6237\u6280\u672f\u6216\u79f0\u591a\u91cd\u79df\u8d41\u6280\u672f\uff0c\u7b80\u79f0 ",Object(r.b)("inlineCode",{parentName:"p"},"SaaS"),"\uff0c\u662f\u4e00\u79cd\u8f6f\u4ef6\u67b6\u6784\u6280\u672f\uff0c\u662f\u5b9e\u73b0\u5982\u4f55\u5728\u591a\u7528\u6237\u73af\u5883\u4e0b\uff08\u6b64\u5904\u7684\u591a\u7528\u6237\u4e00\u822c\u662f\u9762\u5411\u4f01\u4e1a\u7528\u6237\uff09\u5171\u7528\u76f8\u540c\u7684\u7cfb\u7edf\u6216\u7a0b\u5e8f\u7ec4\u4ef6\uff0c\u5e76\u4e14\u53ef\u786e\u4fdd\u5404\u7528\u6237\u95f4\u6570\u636e\u7684\u9694\u79bb\u6027\u3002"),Object(r.b)("p",null,Object(r.b)("strong",{parentName:"p"},"\u7b80\u5355\u8bb2\uff1a\u5728\u4e00\u53f0\u670d\u52a1\u5668\u4e0a\u8fd0\u884c\u5355\u4e2a\u5e94\u7528\u5b9e\u4f8b\uff0c\u5b83\u4e3a\u591a\u4e2a\u79df\u6237\uff08\u5ba2\u6237\uff09\u63d0\u4f9b\u670d\u52a1\u3002"),"\u4ece\u5b9a\u4e49\u4e2d\u6211\u4eec\u53ef\u4ee5\u7406\u89e3\uff1a\u591a\u79df\u6237\u662f\u4e00\u79cd\u67b6\u6784\uff0c\u76ee\u7684\u662f\u4e3a\u4e86\u8ba9\u591a\u7528\u6237\u73af\u5883\u4e0b\u4f7f\u7528\u540c\u4e00\u5957\u7a0b\u5e8f\uff0c\u4e14\u4fdd\u8bc1\u7528\u6237\u95f4\u6570\u636e\u9694\u79bb\u3002\u90a3\u4e48\u91cd\u70b9\u5c31\u5f88\u6d45\u663e\u6613\u61c2\u4e86\uff0c\u591a\u79df\u6237\u7684\u91cd\u70b9\u5c31\u662f\u540c\u4e00\u5957\u7a0b\u5e8f\u4e0b\u5b9e\u73b0\u591a\u7528\u6237\u6570\u636e\u7684\u9694\u79bb\u3002"),Object(r.b)("h2",{id:"103-\u5b9e\u73b0\u591a\u79df\u6237\u65b9\u6848"},"10.3 \u5b9e\u73b0\u591a\u79df\u6237\u65b9\u6848"),Object(r.b)("h3",{id:"1031-\u72ec\u7acb\u6570\u636e\u5e93"},"10.3.1 \u72ec\u7acb\u6570\u636e\u5e93"),Object(r.b)("p",null,"\u8fd9\u662f\u7b2c\u4e00\u79cd\u65b9\u6848\uff0c\u5373\u4e00\u4e2a\u79df\u6237\u4e00\u4e2a\u6570\u636e\u5e93\uff0c\u8fd9\u79cd\u65b9\u6848\u7684\u7528\u6237\u6570\u636e\u9694\u79bb\u7ea7\u522b\u6700\u9ad8\uff0c\u5b89\u5168\u6027\u6700\u597d\uff0c\u4f46\u6210\u672c\u8f83\u9ad8\u3002"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u4f18\u70b9\uff1a"),"\n\u4e3a\u4e0d\u540c\u7684\u79df\u6237\u63d0\u4f9b\u72ec\u7acb\u7684\u6570\u636e\u5e93\uff0c\u6709\u52a9\u4e8e\u7b80\u5316\u6570\u636e\u6a21\u578b\u7684\u6269\u5c55\u8bbe\u8ba1\uff0c\u6ee1\u8db3\u4e0d\u540c\u79df\u6237\u7684\u72ec\u7279\u9700\u6c42\uff1b\u5982\u679c\u51fa\u73b0\u6545\u969c\uff0c\u6062\u590d\u6570\u636e\u6bd4\u8f83\u7b80\u5355\u3002")),Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u7f3a\u70b9\uff1a"),"\n\u589e\u591a\u4e86\u6570\u636e\u5e93\u7684\u5b89\u88c5\u6570\u91cf\uff0c\u968f\u4e4b\u5e26\u6765\u7ef4\u62a4\u6210\u672c\u548c\u8d2d\u7f6e\u6210\u672c\u7684\u589e\u52a0\u3002 \u8fd9\u79cd\u65b9\u6848\u4e0e\u4f20\u7edf\u7684\u4e00\u4e2a\u5ba2\u6237\u3001\u4e00\u5957\u6570\u636e\u3001\u4e00\u5957\u90e8\u7f72\u7c7b\u4f3c\uff0c\u5dee\u522b\u53ea\u5728\u4e8e\u8f6f\u4ef6\u7edf\u4e00\u90e8\u7f72\u5728\u8fd0\u8425\u5546\u90a3\u91cc\u3002\u5982\u679c\u9762\u5bf9\u7684\u662f\u94f6\u884c\u3001\u533b\u9662\u7b49\u9700\u8981\u975e\u5e38\u9ad8\u6570\u636e\u9694\u79bb\u7ea7\u522b\u7684\u79df\u6237\uff0c\u53ef\u4ee5\u9009\u62e9\u8fd9\u79cd\u6a21\u5f0f\uff0c\u63d0\u9ad8\u79df\u7528\u7684\u5b9a\u4ef7\u3002\u5982\u679c\u5b9a\u4ef7\u8f83\u4f4e\uff0c\u4ea7\u54c1\u8d70\u4f4e\u4ef7\u8def\u7ebf\uff0c\u8fd9\u79cd\u65b9\u6848\u4e00\u822c\u5bf9\u8fd0\u8425\u5546\u6765\u8bf4\u662f\u65e0\u6cd5\u627f\u53d7\u7684\u3002"))),Object(r.b)("h3",{id:"1032-\u5171\u4eab\u6570\u636e\u5e93\uff0c\u72ec\u7acb-schema"},"10.3.2 \u5171\u4eab\u6570\u636e\u5e93\uff0c\u72ec\u7acb ",Object(r.b)("inlineCode",{parentName:"h3"},"Schema")),Object(r.b)("p",null,"\u8fd9\u662f\u7b2c\u4e8c\u79cd\u65b9\u6848\uff0c\u5373\u591a\u4e2a\u6216\u6240\u6709\u79df\u6237\u5171\u4eab ",Object(r.b)("inlineCode",{parentName:"p"},"Database"),"\uff0c\u4f46\u662f\u6bcf\u4e2a\u79df\u6237\u4e00\u4e2a ",Object(r.b)("inlineCode",{parentName:"p"},"Schema"),"\uff08\u4e5f\u53ef\u53eb\u505a\u4e00\u4e2a user\uff09\u3002\u5e95\u5c42\u5e93\u6bd4\u5982\u662f\uff1a",Object(r.b)("inlineCode",{parentName:"p"},"SqlServer"),"\u3001",Object(r.b)("inlineCode",{parentName:"p"},"Oracle")," \u7b49\uff0c\u4e00\u4e2a\u6570\u636e\u5e93\u4e0b\u53ef\u4ee5\u6709\u591a\u4e2a ",Object(r.b)("inlineCode",{parentName:"p"},"Schema"),"\u3002"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u4f18\u70b9\uff1a"),"\n\u4e3a\u5b89\u5168\u6027\u8981\u6c42\u8f83\u9ad8\u7684\u79df\u6237\u63d0\u4f9b\u4e86\u4e00\u5b9a\u7a0b\u5ea6\u7684\u903b\u8f91\u6570\u636e\u9694\u79bb\uff0c\u5e76\u4e0d\u662f\u5b8c\u5168\u9694\u79bb\uff1b\u6bcf\u4e2a\u6570\u636e\u5e93\u53ef\u652f\u6301\u66f4\u591a\u7684\u79df\u6237\u6570\u91cf\u3002")),Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u7f3a\u70b9\uff1a"),"\n\u5982\u679c\u51fa\u73b0\u6545\u969c\uff0c\u6570\u636e\u6062\u590d\u6bd4\u8f83\u56f0\u96be\uff0c\u56e0\u4e3a\u6062\u590d\u6570\u636e\u5e93\u5c06\u7275\u6d89\u5230\u5176\u4ed6\u79df\u6237\u7684\u6570\u636e\uff1b \u5982\u679c\u9700\u8981\u8de8\u79df\u6237\u7edf\u8ba1\u6570\u636e\uff0c\u5b58\u5728\u4e00\u5b9a\u56f0\u96be\u3002"))),Object(r.b)("h3",{id:"1033-\u5171\u4eab\u6570\u636e\u5e93\uff0c\u5171\u4eab-schema"},"10.3.3 \u5171\u4eab\u6570\u636e\u5e93\uff0c\u5171\u4eab ",Object(r.b)("inlineCode",{parentName:"h3"},"Schema")),Object(r.b)("p",null,"\u5171\u4eab\u6570\u636e\u8868 \u8fd9\u662f\u7b2c\u4e09\u79cd\u65b9\u6848\uff0c\u5373\u79df\u6237\u5171\u4eab\u540c\u4e00\u4e2a ",Object(r.b)("inlineCode",{parentName:"p"},"Database"),"\u3001\u540c\u4e00\u4e2a ",Object(r.b)("inlineCode",{parentName:"p"},"Schema"),"\uff0c\u4f46\u5728\u8868\u4e2d\u589e\u52a0 ",Object(r.b)("strong",{parentName:"p"},Object(r.b)("inlineCode",{parentName:"strong"},"TenantId"))," \u591a\u79df\u6237\u7684\u6570\u636e\u5b57\u6bb5\u3002\u8fd9\u662f\u5171\u4eab\u7a0b\u5ea6\u6700\u9ad8\u3001\u9694\u79bb\u7ea7\u522b\u6700\u4f4e\u7684\u6a21\u5f0f\u3002 \u5373\u6bcf\u63d2\u5165\u4e00\u6761\u6570\u636e\u65f6\u90fd\u9700\u8981\u6709\u4e00\u4e2a\u5ba2\u6237\u7684\u6807\u8bc6\u3002\u8fd9\u6837\u624d\u80fd\u5728\u540c\u4e00\u5f20\u8868\u4e2d\u533a\u5206\u51fa\u4e0d\u540c\u5ba2\u6237\u7684\u6570\u636e\u3002"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u4f18\u70b9\uff1a"),"\n\u4e09\u79cd\u65b9\u6848\u6bd4\u8f83\uff0c\u7b2c\u4e09\u79cd\u65b9\u6848\u7684\u7ef4\u62a4\u548c\u8d2d\u7f6e\u6210\u672c\u6700\u4f4e\uff0c\u5141\u8bb8\u6bcf\u4e2a\u6570\u636e\u5e93\u652f\u6301\u7684\u79df\u6237\u6570\u91cf\u6700\u591a\u3002")),Object(r.b)("li",{parentName:"ul"},Object(r.b)("p",{parentName:"li"},Object(r.b)("strong",{parentName:"p"},"\u7f3a\u70b9\uff1a"),"\n\u9694\u79bb\u7ea7\u522b\u6700\u4f4e\uff0c\u5b89\u5168\u6027\u6700\u4f4e\uff0c\u9700\u8981\u5728\u8bbe\u8ba1\u5f00\u53d1\u65f6\u52a0\u5927\u5bf9\u5b89\u5168\u7684\u5f00\u53d1\u91cf\uff1b \u6570\u636e\u5907\u4efd\u548c\u6062\u590d\u6700\u56f0\u96be\uff0c\u9700\u8981\u9010\u8868\u9010\u6761\u5907\u4efd\u548c\u8fd8\u539f\u3002"))),Object(r.b)("h2",{id:"104-\u591a\u79df\u6237\u4f7f\u7528\u65b9\u6848"},"10.4 \u591a\u79df\u6237\u4f7f\u7528\u65b9\u6848"),Object(r.b)("p",null,Object(r.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u652f\u6301\u4ee5\u4e0a\u4e09\u79cd\u591a\u79df\u6237\u5b9e\u73b0\u65b9\u6848\uff0c\u4f7f\u7528\u7b80\u5355\u4e14\u5bb9\u6613\u7ef4\u62a4\u3002\u4e0b\u9762\u5206\u522b\u4f7f\u7528\u4e09\u79cd\u4e0d\u540c\u65b9\u5f0f\u6f14\u793a\u591a\u79df\u6237\u65b9\u6848\u7528\u6cd5\u3002"),Object(r.b)("h2",{id:"105-\u57fa\u4e8e-tenantid-\u7684\u65b9\u5f0f"},"10.5 \u57fa\u4e8e ",Object(r.b)("inlineCode",{parentName:"h2"},"TenantId")," \u7684\u65b9\u5f0f"),Object(r.b)("p",null,"\u6b64\u65b9\u5f0f\u5728\u4e2d\u5c0f\u578b\u4f01\u4e1a\u7cfb\u7edf\u4e2d\u6700\u4e3a\u5e38\u7528\uff0c\u7ef4\u62a4\u6210\u672c\u4f4e\uff0c\u8d2d\u7f6e\u6210\u672c\u4f4e\u3002"),Object(r.b)("h3",{id:"1051-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.5.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{6-7} title="Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"',"{6-7}":!0,title:'"Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class MultiTenantDbContext : AppDbContext\n {\n public MultiTenantDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-important alert alert--info"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u591a\u79df\u6237\u64cd\u4f5c\u5efa\u8bae\u5355\u72ec\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u800c\u4e14\u9700\u6307\u5b9a ",Object(r.b)("inlineCode",{parentName:"p"},"MultiTenantDbContextLocator")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u3002"))),Object(r.b)("h3",{id:"1052-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.5.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{14}","{14}":!0}),"using Fur.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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 options.AddDbPool(DbProvider.Sqlite);\n });\n }\n }\n}\n")),Object(r.b)("h3",{id:"1053-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e"},"10.5.3 \u6dfb\u52a0 ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u79cd\u5b50\u6570\u636e"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{8,12-28} title="Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"',"{8,12-28}":!0,title:'"Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Fur.EntityFramework.Core\n{\n public class TenantSeedData : IEntitySeedData\n {\n public IEnumerable HasData(DbContext dbContext, Type dbContextLocator)\n {\n return new List\n {\n new Tenant\n {\n TenantId=Guid.Parse("383AFB88-F519-FFF8-B364-6D563BF3687F"),\n Name="\u9ed8\u8ba4\u79df\u6237",\n Host="localhost:44313",\n CreatedTime=DateTime.Parse("2020-10-06 20:19:07")\n },\n new Tenant\n {\n TenantId=Guid.Parse("C5798CB6-16D6-0F42-EB56-59C695353BC0"),\n Name="\u5176\u4ed6\u79df\u6237",\n Host="localhost:5000",\n CreatedTime=DateTime.Parse("2020-10-06 20:20:32")\n }\n };\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u8bf4\u660e")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u8be5\u6b65\u9aa4\u53ea\u5728 ",Object(r.b)("inlineCode",{parentName:"p"},"Code First")," \u65b9\u5f0f\u6267\u884c\uff0c",Object(r.b)("inlineCode",{parentName:"p"},"Database First")," \u65e0\u9700\u914d\u7f6e\u79cd\u5b50\u6570\u636e\u3002"))),Object(r.b)("h3",{id:"1054-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868"},"10.5.4 \u6839\u636e\u6a21\u578b\u521b\u5efa ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u8868"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Add-Migration add_tenant_table -Context MultiTenantDbContext\n")),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Update-Database -Context MultiTenantDbContext\n")),Object(r.b)("h3",{id:"1055-\u5b9e\u73b0-imultitenantontable-\u63a5\u53e3"},"10.5.5 \u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"h3"},"IMultiTenantOnTable")," \u63a5\u53e3"),Object(r.b)("p",null,"\u5728\u9700\u8981\u591a\u79df\u6237\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"p"},"IMultiTenantOnTable")," \u63a5\u53e3\uff0c\u5982\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{8,14-17}","{8,14-17}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing System;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class FurDbContext : AppDbContext, IMultiTenantOnTable, IModelBuilderFilter\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public Guid? GetTenantId()\n {\n return base.Tenant.TenantId;\n }\n }\n}\n')),Object(r.b)("p",null,"\u5728 ",Object(r.b)("inlineCode",{parentName:"p"},"GetTenantId()")," \u65b9\u6cd5\u4e2d\uff0c\u9996\u5148\u83b7\u53d6\u8bf7\u6c42\u7684 ",Object(r.b)("inlineCode",{parentName:"p"},"\u4e3b\u673a\u5730\u5740"),"\uff0c\u7136\u540e\u6839\u636e\u4e3b\u673a\u5730\u5740\u67e5\u8be2\u5bf9\u5e94\u7684\u79df\u6237 ",Object(r.b)("inlineCode",{parentName:"p"},"TenantIdId"),"\uff0c\u907f\u514d\u591a\u6b21\u67e5\u8be2\u6570\u636e\u5e93\uff0c\u8fd9\u91cc\u4f7f\u7528\u4e86 ",Object(r.b)("inlineCode",{parentName:"p"},"IMemoryCache")," \u5185\u5b58\u7f13\u5b58\u3002"),Object(r.b)("h3",{id:"1056-\u5b9e\u73b0-imodelbuilderfilter-\u63a5\u53e3"},"10.5.6 \u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"h3"},"IModelBuilderFilter")," \u63a5\u53e3"),Object(r.b)("p",null,Object(r.b)("inlineCode",{parentName:"p"},"IModelBuilderFilter")," \u63a5\u53e3\u662f\u5168\u5c40\u67e5\u8be2\u8fc7\u6ee4\u5668\u5b9e\u73b0\u63a5\u53e3\uff0c\u6240\u4ee5\u6211\u4eec\u9700\u8981\u914d\u7f6e\u5b9e\u4f53 ",Object(r.b)("inlineCode",{parentName:"p"},"TenantId")," \u8fc7\u6ee4\u5668"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{9,20-23}","{9,20-23}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class FurDbContext : AppDbContext, IMultiTenantOnTable, IModelBuilderFilter\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public Guid? GetTenantId()\n {\n return base.Tenant.TenantId;\n }\n\n public void OnCreating(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.HasQueryFilter(TenantIdQueryFilterExpression(entityBuilder, GetTenantId().Value));\n }\n }\n}\n')),Object(r.b)("h3",{id:"1057-\u91cd\u5199-savingchangesevent-\u4e8b\u4ef6\u65b9\u6cd5"},"10.5.7 \u91cd\u5199 ",Object(r.b)("inlineCode",{parentName:"h3"},"SavingChangesEvent")," \u4e8b\u4ef6\u65b9\u6cd5"),Object(r.b)("p",null,"\u901a\u8fc7\u4e0a\u9762\u7684\u6b65\u9aa4\uff0c\u6211\u4eec\u5df2\u7ecf\u89e3\u51b3\u4e86 ",Object(r.b)("inlineCode",{parentName:"p"},"\u67e5\u8be2")," \u79df\u6237\u8fc7\u6ee4\u529f\u80fd\uff0c\u4f46\u662f ",Object(r.b)("inlineCode",{parentName:"p"},"\u65b0\u589e")," \u548c ",Object(r.b)("inlineCode",{parentName:"p"},"\u66f4\u65b0")," \u8fd8\u672a\u5904\u7406\u3002"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"\u65b0\u589e")," \u6570\u636e\u7684\u65f6\u5019\u81ea\u52a8\u8bbe\u7f6e ",Object(r.b)("inlineCode",{parentName:"li"},"TenantId")," \u7684\u503c"),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"\u66f4\u65b0")," \u6570\u636e\u7684\u65f6\u5019\u6392\u9664 ",Object(r.b)("inlineCode",{parentName:"li"},"TenantId")," \u5c5e\u6027\u66f4\u65b0")),Object(r.b)("p",null,"\u5b9e\u73b0\u4e0a\u9762\u7684\u6b65\u9aa4\u5f88\u7b80\u5355\uff0c\u53ea\u9700\u8981\u91cd\u5199 ",Object(r.b)("inlineCode",{parentName:"p"},"SavingChangesEvent")," \u4e8b\u4ef6\u65b9\u6cd5\u5373\u53ef\u3002"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{26-48}","{26-48}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;\nusing System;\nusing System.Linq;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class FurDbContext : AppDbContext, IMultiTenantOnTable, IModelBuilderFilter\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public Guid? GetTenantId()\n {\n return base.Tenant.TenantId;\n }\n\n public void OnCreating(ModelBuilder modelBuilder, EntityTypeBuilder entityBuilder, DbContext dbContext, Type dbContextLocator)\n {\n entityBuilder.HasQueryFilter(TenantIdQueryFilterExpression(entityBuilder, GetTenantId().Value));\n }\n\n protected override void SavingChangesEvent(object sender, SavingChangesEventArgs e)\n {\n // \u83b7\u53d6\u5f53\u524d\u4e8b\u4ef6\u5bf9\u5e94\u4e0a\u4e0b\u6587\n var dbContext = sender as FurDbContext;\n\n // \u83b7\u53d6\u6240\u6709\u65b0\u589e\u548c\u66f4\u65b0\u7684\u5b9e\u4f53\n var entities = dbContext.ChangeTracker.Entries().Where(u => u.State == EntityState.Added || u.State == EntityState.Modified);\n\n foreach (var entity in entities)\n {\n switch (entity.State)\n {\n // \u81ea\u52a8\u8bbe\u7f6e\u79df\u6237Id\n case EntityState.Added:\n entity.Property(nameof(Entity.TenantId)).CurrentValue = base.TenantId;\n break;\n // \u6392\u9664\u79df\u6237Id\n case EntityState.Modified:\n entity.Property(nameof(Entity.TenantId)).IsModified = false;\n break;\n }\n }\n }\n }\n}\n')),Object(r.b)("img",{src:Object(o.a)("img/saas1.png")}),Object(r.b)("h2",{id:"106-\u57fa\u4e8e-database-\u7684\u65b9\u5f0f"},"10.6 \u57fa\u4e8e ",Object(r.b)("inlineCode",{parentName:"h2"},"Database")," \u7684\u65b9\u5f0f"),Object(r.b)("p",null,"\u6b64\u65b9\u5f0f\u5728\u4e2d\u5927\u578b\u4f01\u4e1a\u7cfb\u7edf\u4e2d\u6700\u4e3a\u5e38\u7528\uff0c\u4e00\u4e2a\u79df\u6237\uff08\u5ba2\u6237\uff09\u4e00\u4e2a\u72ec\u7acb\u7684\u6570\u636e\u5e93\u3002"),Object(r.b)("h3",{id:"1061-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.6.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{6-7} title="Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"',"{6-7}":!0,title:'"Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class MultiTenantDbContext : AppDbContext\n {\n public MultiTenantDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-important alert alert--info"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u591a\u79df\u6237\u64cd\u4f5c\u5efa\u8bae\u5355\u72ec\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u800c\u4e14\u9700\u6307\u5b9a ",Object(r.b)("inlineCode",{parentName:"p"},"MultiTenantDbContextLocator")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u3002"))),Object(r.b)("h3",{id:"1062-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.6.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{13,14}","{13,14}":!0}),"using Fur.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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.AddDb(DbProvider.Sqlite);\n options.AddDbPool(DbProvider.Sqlite);\n });\n }\n }\n}\n")),Object(r.b)("div",{className:"admonition admonition-caution alert alert--warning"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 16 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u9700\u8981 ",Object(r.b)("inlineCode",{parentName:"p"},"Database")," \u591a\u79df\u6237\u65b9\u6848\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u9700\u8981\u91c7\u7528 ",Object(r.b)("inlineCode",{parentName:"p"},"AddDb")," \u6ce8\u518c\uff0c\u800c\u4e0d\u662f ",Object(r.b)("inlineCode",{parentName:"p"},"AddDbPool"),"\u3002\u539f\u56e0\u662f ",Object(r.b)("inlineCode",{parentName:"p"},"AddDbPool")," \u65b9\u5f0f\u6ce8\u518c\u540e\u7eed\u4e0d\u652f\u6301 ",Object(r.b)("inlineCode",{parentName:"p"},"OnConfiguring")," \u91cd\u5199\uff01\uff01\uff01"))),Object(r.b)("h3",{id:"1063-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e"},"10.6.3 \u6dfb\u52a0 ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u79cd\u5b50\u6570\u636e"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{8,12-30} title="Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"',"{8,12-30}":!0,title:'"Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Fur.EntityFramework.Core\n{\n public class TenantSeedData : IEntitySeedData\n {\n public IEnumerable HasData(DbContext dbContext, Type dbContextLocator)\n {\n return new List\n {\n new Tenant\n {\n TenantId=Guid.Parse("383AFB88-F519-FFF8-B364-6D563BF3687F"),\n Name="\u9ed8\u8ba4\u79df\u6237",\n Host="localhost:44313",\n CreatedTime=DateTime.Parse("2020-10-06 20:19:07"),\n ConnectionString="Data Source=./Fur.db" // \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32\n },\n new Tenant\n {\n TenantId=Guid.Parse("C5798CB6-16D6-0F42-EB56-59C695353BC0"),\n Name="\u5176\u4ed6\u79df\u6237",\n Host="localhost:5000",\n CreatedTime=DateTime.Parse("2020-10-06 20:20:32"),\n ConnectionString="Data Source=./Fur2.db" // \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32\n }\n };\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u8bf4\u660e")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u8be5\u6b65\u9aa4\u53ea\u5728 ",Object(r.b)("inlineCode",{parentName:"p"},"Code First")," \u65b9\u5f0f\u6267\u884c\uff0c",Object(r.b)("inlineCode",{parentName:"p"},"Database First")," \u65e0\u9700\u914d\u7f6e\u79cd\u5b50\u6570\u636e\u3002"))),Object(r.b)("h3",{id:"1064-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868"},"10.6.4 \u6839\u636e\u6a21\u578b\u521b\u5efa ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u8868"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Add-Migration add_tenant_table -Context MultiTenantDbContext\n")),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Update-Database -Context MultiTenantDbContext\n")),Object(r.b)("h3",{id:"1065-\u5b9e\u73b0-imultitenantondatabase-\u63a5\u53e3"},"10.6.5 \u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"h3"},"IMultiTenantOnDatabase")," \u63a5\u53e3"),Object(r.b)("p",null,"\u5728\u9700\u8981\u591a\u79df\u6237\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"p"},"IMultiTenantOnDatabase")," \u63a5\u53e3\uff0c\u5982\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{6,12-15}","{6,12-15}":!0}),"using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n public class FurDbContext : AppDbContext, IMultiTenantOnDatabase\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public string GetDatabaseConnectionString()\n {\n return base.Tenant.ConnectionString;\n }\n }\n}\n")),Object(r.b)("h3",{id:"1066-\u91cd\u5199-onconfiguring-\u65b9\u6cd5"},"10.6.6 \u91cd\u5199 ",Object(r.b)("inlineCode",{parentName:"h3"},"OnConfiguring")," \u65b9\u6cd5"),Object(r.b)("p",null,"\u5728\u9700\u8981\u591a\u79df\u6237\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u91cd\u5199 ",Object(r.b)("inlineCode",{parentName:"p"},"OnConfiguring")," \u65b9\u6cd5\u5e76\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{12-17}","{12-17}":!0}),"using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n public class FurDbContext : AppDbContext, IMultiTenantOnDatabase\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)\n {\n optionsBuilder.UseSqlite(GetDatabaseConnectionString());\n\n base.OnConfiguring(optionsBuilder);\n }\n\n public string GetDatabaseConnectionString()\n {\n return base.Tenant.ConnectionString;\n }\n }\n}\n")),Object(r.b)("img",{src:Object(o.a)("img/saas2.png")}),Object(r.b)("h2",{id:"107-\u57fa\u4e8e-schema-\u7684\u65b9\u5f0f"},"10.7 \u57fa\u4e8e ",Object(r.b)("inlineCode",{parentName:"h2"},"Schema")," \u7684\u65b9\u5f0f"),Object(r.b)("p",null,"\u6b64\u65b9\u5f0f\u5728\u4e2d\u5c0f\u578b\u4f01\u4e1a\u7cfb\u7edf\u4e2d\u4e5f\u4e0d\u5c11\u89c1\uff0c\u4e00\u4e2a\u79df\u6237\uff08\u5ba2\u6237\uff09\u5171\u4eab\u6570\u636e\u5e93\u4e14\u4e0d\u540c ",Object(r.b)("inlineCode",{parentName:"p"},"Schema"),"\u3002"),Object(r.b)("h3",{id:"1071-\u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.7.1 \u521b\u5efa\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{6-7} title="Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"',"{6-7}":!0,title:'"Fur.EntityFramework.Core\\DbContexts\\MultiTenantDbContext.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class MultiTenantDbContext : AppDbContext\n {\n public MultiTenantDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-important alert alert--info"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u591a\u79df\u6237\u64cd\u4f5c\u5efa\u8bae\u5355\u72ec\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u800c\u4e14\u9700\u6307\u5b9a ",Object(r.b)("inlineCode",{parentName:"p"},"MultiTenantDbContextLocator")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\u3002"))),Object(r.b)("h3",{id:"1072-\u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"10.7.2 \u6ce8\u518c\u591a\u79df\u6237\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{14}","{14}":!0}),"using Fur.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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 options.AddDbPool(DbProvider.Sqlite);\n });\n }\n }\n}\n")),Object(r.b)("h3",{id:"1073-\u6dfb\u52a0-tenant-\u79cd\u5b50\u6570\u636e"},"10.7.3 \u6dfb\u52a0 ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u79cd\u5b50\u6570\u636e"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{8,12-30} title="Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"',"{8,12-30}":!0,title:'"Fur.EntityFramework.Core\\SeedDatas\\TenantSeedData.cs"'}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\nusing System;\nusing System.Collections.Generic;\n\nnamespace Fur.EntityFramework.Core\n{\n public class TenantSeedData : IEntitySeedData\n {\n public IEnumerable HasData(DbContext dbContext, Type dbContextLocator)\n {\n return new List\n {\n new Tenant\n {\n TenantId=Guid.Parse("383AFB88-F519-FFF8-B364-6D563BF3687F"),\n Name="\u9ed8\u8ba4\u79df\u6237",\n Host="localhost:44313",\n CreatedTime=DateTime.Parse("2020-10-06 20:19:07"),\n Schema="dbo" // Schema\n },\n new Tenant\n {\n TenantId=Guid.Parse("C5798CB6-16D6-0F42-EB56-59C695353BC0"),\n Name="\u5176\u4ed6\u79df\u6237",\n Host="localhost:5000",\n CreatedTime=DateTime.Parse("2020-10-06 20:20:32"),\n Schema="fur" // Schema\n }\n };\n }\n }\n}\n')),Object(r.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u8bf4\u660e")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u8be5\u6b65\u9aa4\u53ea\u5728 ",Object(r.b)("inlineCode",{parentName:"p"},"Code First")," \u65b9\u5f0f\u6267\u884c\uff0c",Object(r.b)("inlineCode",{parentName:"p"},"Database First")," \u65e0\u9700\u914d\u7f6e\u79cd\u5b50\u6570\u636e\u3002"))),Object(r.b)("h3",{id:"1074-\u6839\u636e\u6a21\u578b\u521b\u5efa-tenant-\u8868"},"10.7.4 \u6839\u636e\u6a21\u578b\u521b\u5efa ",Object(r.b)("inlineCode",{parentName:"h3"},"Tenant")," \u8868"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Add-Migration add_tenant_table -Context MultiTenantDbContext\n")),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Update-Database -Context MultiTenantDbContext\n")),Object(r.b)("h3",{id:"1075-\u5b9e\u73b0-imultitenantonschema-\u63a5\u53e3"},"10.7.5 \u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"h3"},"IMultiTenantOnSchema")," \u63a5\u53e3"),Object(r.b)("p",null,"\u5728\u9700\u8981\u591a\u79df\u6237\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u5b9e\u73b0 ",Object(r.b)("inlineCode",{parentName:"p"},"IMultiTenantOnSchema")," \u63a5\u53e3\uff0c\u5982\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{6,12-15}","{6,12-15}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Sqlite3ConnectionString")]\n public class FurDbContext : AppDbContext, IMultiTenantOnSchema\n {\n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n\n public string GetSchemaName()\n {\n return base.Tenant.Schema;\n }\n }\n}\n')),Object(r.b)("h3",{id:"1076-\u5173\u4e8e-code-first-\u6570\u636e\u8fc1\u79fb"},"10.7.6 \u5173\u4e8e ",Object(r.b)("inlineCode",{parentName:"h3"},"Code First \u6570\u636e\u8fc1\u79fb")),Object(r.b)("p",null,"\u57fa\u4e8e ",Object(r.b)("inlineCode",{parentName:"p"},"Schema")," \u65b9\u5f0f\u6bd4\u8f83\u7279\u522b\uff0c\u751f\u6210\u6570\u636e\u8fc1\u79fb\u7684\u65f6\u5019\u6ca1\u529e\u6cd5\u83b7\u53d6\u79df\u6237\u4fe1\u606f\uff0c\u6240\u4ee5\u5efa\u8bae",Object(r.b)("strong",{parentName:"p"},"\u5206\u5f00\u591a\u6b21\u8fc1\u79fb"),"\uff0c\u5982\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),'public string GetSchemaName()\n{\n return base.Tenant.Schema?? "\u79df\u6237\u4e00Schema";\n}\n')),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),'public string GetSchemaName()\n{\n return base.Tenant.Schema?? "\u79df\u6237\u4e8cSchema";\n}\n')),Object(r.b)("p",null,"\u8fd9\u6837\u5c31\u53ef\u4ee5\u5728\u8fc1\u79fb\u7684\u65f6\u5019\u751f\u6210\u591a\u6b21\u8fc1\u79fb\u4e86\u3002"),Object(r.b)("h2",{id:"108-\u53cd\u9988\u4e0e\u5efa\u8bae"},"10.8 \u53cd\u9988\u4e0e\u5efa\u8bae"),Object(r.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e0e\u6211\u4eec\u4ea4\u6d41")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u7ed9 Fur \u63d0 ",Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://gitee.com/monksoul/Fur/issues/new?issue"}),"Issue"),"\u3002"))))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/3e869f93.43ad9133.js b/handbook/build/3e869f93.3b6f6bba.js similarity index 51% rename from handbook/build/3e869f93.43ad9133.js rename to handbook/build/3e869f93.3b6f6bba.js index da390f18c7a..43dd53f7191 100644 --- a/handbook/build/3e869f93.43ad9133.js +++ b/handbook/build/3e869f93.3b6f6bba.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[24],{138:function(e,t,n){"use strict";n.d(t,"a",(function(){return d})),n.d(t,"b",(function(){return O}));var a=n(0),r=n.n(a);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 b(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 p=r.a.createContext({}),l=function(e){var t=r.a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):b(b({},t),e)),n},d=function(e){var t=l(e.components);return r.a.createElement(p.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},m=r.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,o=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),d=l(n),m=a,O=d["".concat(o,".").concat(m)]||d[m]||s[m]||i;return n?r.a.createElement(O,b(b({ref:t},p),{},{components:n})):r.a.createElement(O,b({ref:t},p))}));function O(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,o=new Array(i);o[0]=m;var b={};for(var c in t)hasOwnProperty.call(t,c)&&(b[c]=t[c]);b.originalType=e,b.mdxType="string"==typeof e?e:a,o[1]=b;for(var p=2;pAppDbContext",id:"912-appdbcontext",children:[]},{value:"9.1.3 AppDbContext \u548c DbContext \u533a\u522b",id:"913-appdbcontext-\u548c-dbcontext-\u533a\u522b",children:[]},{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",children:[{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",children:[]},{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",children:[]}]},{value:"9.1.5 \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32",id:"915-\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32",children:[{value:"9.1.5.1 Startup \u65b9\u5f0f\u914d\u7f6e",id:"9151-startup-\u65b9\u5f0f\u914d\u7f6e",children:[]},{value:"9.1.5.2 [AppDbContext] \u65b9\u5f0f\u914d\u7f6e",id:"9152-appdbcontext-\u65b9\u5f0f\u914d\u7f6e",children:[]},{value:"9.1.5.3 OnConfiguring \u65b9\u5f0f\u914d\u7f6e",id:"9153-onconfiguring-\u65b9\u5f0f\u914d\u7f6e",children:[]}]},{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",children:[]},{value:"9.1.7 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c",id:"917-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c",children:[]},{value:"9.1.8 \u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61",id:"918-\u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61",children:[]},{value:"9.1.9 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"919-\u53cd\u9988\u4e0e\u5efa\u8bae",children:[]}],p={rightToc:c};function l(e){var t=e.components,n=Object(r.a)(e,["components"]);return Object(i.b)("wrapper",Object(a.a)({},p,n,{components:t,mdxType:"MDXLayout"}),Object(i.b)("h2",{id:"911-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.1.1 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(i.b)("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"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u4e2d\uff0c\u9ed8\u8ba4\u96c6\u6210\u4e86\u5fae\u8f6f\u4eb2\u513f\u5b50\uff1a",Object(i.b)("inlineCode",{parentName:"p"},"EntityFramework Core")," \uff0c\u4e5f\u5c31\u662f\u901a\u5e38\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6307\u7684\u662f ",Object(i.b)("inlineCode",{parentName:"p"},"DbContext")," \u7c7b\u6216\u5b83\u7684\u5b9e\u73b0\u7c7b\u3002"),Object(i.b)("h2",{id:"912-appdbcontext"},"9.1.2 ",Object(i.b)("inlineCode",{parentName:"h2"},"AppDbContext")),Object(i.b)("p",null,"\u5728\u6211\u4eec\u5b9e\u9645\u9879\u76ee\u5f00\u53d1\u8fc7\u7a0b\u4e2d\uff0c\u4f7f\u7528 ",Object(i.b)("inlineCode",{parentName:"p"},"EFCore")," \u63d0\u4f9b\u7684 ",Object(i.b)("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"),Object(i.b)("p",null,"\u6240\u4ee5\uff0c",Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",Object(i.b)("inlineCode",{parentName:"p"},"AppDbContext")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u8be5\u4e0a\u4e0b\u6587\u7ee7\u627f\u81ea ",Object(i.b)("inlineCode",{parentName:"p"},"DbContext"),"\u3002"),Object(i.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u8bf4\u660e")),Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},"\u540e\u7eed\u7ae0\u8282\uff0c\u7686\u91c7\u7528 ",Object(i.b)("inlineCode",{parentName:"p"},"EFCore")," \u4ee3\u66ff ",Object(i.b)("inlineCode",{parentName:"p"},"EntityFramework Core"),"\u3002"))),Object(i.b)("h2",{id:"913-appdbcontext-\u548c-dbcontext-\u533a\u522b"},"9.1.3 ",Object(i.b)("inlineCode",{parentName:"h2"},"AppDbContext")," \u548c ",Object(i.b)("inlineCode",{parentName:"h2"},"DbContext")," \u533a\u522b"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u7ee7\u627f\u81ea ",Object(i.b)("inlineCode",{parentName:"li"},"DbContext"),"\uff0c\u5177\u5907 ",Object(i.b)("inlineCode",{parentName:"li"},"DbContext")," \u6240\u6709\u529f\u80fd\u3002"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u591a\u6570\u636e\u5e93\u64cd\u4f5c\u6cdb\u578b\u7248\u672c\uff0c\u5982\uff1a",Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u81ea\u52a8\u914d\u7f6e\u5b9e\u4f53\u4fe1\u606f\uff0c\u65e0\u9700\u5728 ",Object(i.b)("inlineCode",{parentName:"li"},"OnModelCreating")," \u4e2d\u914d\u7f6e"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u5185\u7f6e\u591a\u79df\u6237\u652f\u6301"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u5168\u5c40\u6a21\u578b\u914d\u7f6e\u62e6\u622a\u5668"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u6570\u636e\u63d0\u4ea4\u66f4\u6539\u591a\u4e2a\u4e8b\u4ef6"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u63d0\u4f9b\u66f4\u52a0\u5f3a\u5927\u7684\u6a21\u578b\u64cd\u4f5c\u80fd\u529b\uff0c\u5982\u679c ",Object(i.b)("inlineCode",{parentName:"li"},"Sql")," \u64cd\u4f5c\uff0c\u8bfb\u5199\u5206\u79bb\u7b49"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u80fd\u591f\u5f97\u5230 ",Object(i.b)("inlineCode",{parentName:"li"},"Fur")," \u6846\u67b6\u66f4\u591a\u7684\u529f\u80fd\u652f\u6301")),Object(i.b)("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"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u4e2d\u4e86\uff0c\u63d0\u4f9b\u4e86\u4e24\u79cd ",Object(i.b)("inlineCode",{parentName:"p"},"AppDbContext")," \u5b9a\u4e49\u65b9\u5f0f\uff1a"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u64cd\u4f5c\u9ed8\u8ba4\u6570\u636e\u5e93"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u64cd\u4f5c N \u4e2a\u6570\u636e\u5e93")),Object(i.b)("p",null,"\u5176\u4e2d ",Object(i.b)("inlineCode",{parentName:"p"},"AppDbContext")," \u9ed8\u8ba4\u7ee7\u627f\u81ea ",Object(i.b)("inlineCode",{parentName:"p"},"AppDbContext"),"\u3002"),Object(i.b)("p",null,"\u4e0b\u9762\u662f\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u521b\u5efa\u7684\u591a\u4e2a\u4f8b\u5b50\uff1a"),Object(i.b)("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"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{1,6,12}","{1,6,12}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("\u8fde\u63a5\u5b57\u7b26\u4e32\u6216appsetting.json \u952e")]\n public class FurDbContext : AppDbContext // \u7ee7\u627f AppDbContext<> \u7c7b\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(i.b)("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"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{1,6,12}","{1,6,12}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.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')),Object(i.b)("div",{className:"admonition admonition-important alert alert--info"},Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},"\u6240\u6709\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u90fd\u5e94\u8be5\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u9879\u76ee\u4e2d\u521b\u5efa\u3002\u5173\u4e8e ",Object(i.b)("inlineCode",{parentName:"p"},"TDbContextLocator")," \u5c06\u5728\u4e0b\u4e00\u7ae0\u8282 \u300a",Object(i.b)("a",Object(a.a)({parentName:"p"},{href:"dbcontext-locator"}),"9.2 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668"),"\u300b\u9610\u8ff0\u3002"))),Object(i.b)("h2",{id:"915-\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32"},"9.1.5 \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32"),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u63d0\u4f9b\u591a\u79cd\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u65b9\u5f0f\uff1a"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"\u5728 ",Object(i.b)("inlineCode",{parentName:"li"},"Startup")," \u4e2d\u6dfb\u52a0\u670d\u52a1\uff1a",Object(i.b)("inlineCode",{parentName:"li"},'AddSqlServerPool("\u8fde\u63a5\u5b57\u7b26\u4e32")')," \u65b9\u5f0f"),Object(i.b)("li",{parentName:"ul"},"\u4f7f\u7528 ",Object(i.b)("inlineCode",{parentName:"li"},'[AppDbContext("\u8fde\u63a5\u5b57\u7b26\u4e32/Key")]')," \u7279\u6027\u65b9\u5f0f\uff08\u53ea\u5728 ",Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext \u5b9e\u73b0\u7c7b\u6709\u6548"),"\uff09",Object(i.b)("strong",{parentName:"li"},"\u63a8\u8350")),Object(i.b)("li",{parentName:"ul"},"\u901a\u8fc7\u91cd\u5199 ",Object(i.b)("inlineCode",{parentName:"li"},"OnConfiguring(DbContextOptionsBuilder optionsBuilder)")," \u914d\u7f6e")),Object(i.b)("h3",{id:"9151-startup-\u65b9\u5f0f\u914d\u7f6e"},"9.1.5.1 ",Object(i.b)("inlineCode",{parentName:"h3"},"Startup")," \u65b9\u5f0f\u914d\u7f6e"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{12-19} title="Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"',"{12-19}":!0,title:'"Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"'}),'using Fur.DependencyInjection;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.EntityFramework.Core\n{\n [Startup(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, "\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, "\u8fde\u63a5\u5b57\u7b26\u4e32");\n });\n }\n }\n}\n')),Object(i.b)("h3",{id:"9152-appdbcontext-\u65b9\u5f0f\u914d\u7f6e"},"9.1.5.2 ",Object(i.b)("inlineCode",{parentName:"h3"},"[AppDbContext]")," \u65b9\u5f0f\u914d\u7f6e"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{1,6}","{1,6}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("DbConnectionString")] // \u652f\u6301 `appsetting.json` \u540d\u6216 \u8fde\u63a5\u5b57\u7b26\u4e32\n public class FurDbContext : AppDbContext\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(i.b)("div",{className:"admonition admonition-tip alert alert--success"},Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"12",height:"16",viewBox:"0 0 12 16"}),Object(i.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u5c0f\u63d0\u793a")),Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u63a8\u8350\u4f7f\u7528\u6b64\u65b9\u5f0f\u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u3002"))),Object(i.b)("p",null,Object(i.b)("strong",{parentName:"p"},Object(i.b)("inlineCode",{parentName:"strong"},"[AppDbContext]"))," \u5185\u7f6e\u5c5e\u6027\uff1a"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"ConnectionString"),"\uff1a\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u6216\u914d\u7f6e\u6587\u4ef6\u4e2d\u7684\u8def\u5f84\uff08\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e\u67e5\u627e\uff09\uff0c\u6216 ",Object(i.b)("inlineCode",{parentName:"li"},"appsetting.json")," \u7684 ",Object(i.b)("inlineCode",{parentName:"li"},"ConnectionStrings")," \u914d\u7f6e\u5b57\u7b26\u4e32"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"TablePrefix"),"\uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u8868\u7edf\u4e00\u524d\u7f00"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"TableSuffix"),"\uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u8868\u7edf\u4e00\u540e\u7f00")),Object(i.b)("h3",{id:"9153-onconfiguring-\u65b9\u5f0f\u914d\u7f6e"},"9.1.5.3 ",Object(i.b)("inlineCode",{parentName:"h3"},"OnConfiguring")," \u65b9\u5f0f\u914d\u7f6e"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{16-20}","{16-20}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n public class FurDbContext : AppDbContext\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurDbContext(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')),Object(i.b)("div",{className:"admonition admonition-important alert alert--info"},Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},"\u8fd9\u4e09\u79cd\u65b9\u5f0f\u53ef\u4ee5\u540c\u65f6\u4f7f\u7528\uff0c\u4f46\u662f\u6709\u4f18\u5148\u7ea7\uff1a",Object(i.b)("inlineCode",{parentName:"p"},"[AppDbContext]")," -> ",Object(i.b)("inlineCode",{parentName:"p"},"Startup")," -> ",Object(i.b)("inlineCode",{parentName:"p"},"OnConfiguring"),"\uff08\u4f4e\u5230\u9ad8\uff09"),Object(i.b)("p",{parentName:"div"},"\u4e5f\u5c31\u662f ",Object(i.b)("inlineCode",{parentName:"p"},"OnConfiguring")," \u914d\u7f6e\u4f1a\u8986\u76d6 ",Object(i.b)("inlineCode",{parentName:"p"},"Startup")," \u914d\u7f6e\uff0c",Object(i.b)("inlineCode",{parentName:"p"},"Startup")," \u914d\u7f6e\u4f1a\u8986\u76d6 ",Object(i.b)("inlineCode",{parentName:"p"},"[AppDbContext]")," \u914d\u7f6e\u6240\u914d\u7f6e\u7684\u8fde\u63a5\u5b57\u7b26\u4e32\u3002"))),Object(i.b)("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"),Object(i.b)("div",{className:"admonition admonition-important alert alert--info"},Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u4e2d\uff0c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u9700\u5b9a\u4e49\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u4e2d\uff0c\u4e14\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u90fd\u5fc5\u987b\u62e5\u6709\u552f\u4e00\u7684 ",Object(i.b)("inlineCode",{parentName:"p"},"DbContextLocator")," \u5b9a\u4f4d\u5668"))),Object(i.b)("h2",{id:"917-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c"},"9.1.7 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c"),Object(i.b)("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\u6539\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u5e76\u6307\u5b9a\u6570\u636e\u5e93\u7c7b\u578b\uff0c\u5982\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{11-13} title="Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"',"{11-13}":!0,title:'"Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"'}),"using Fur.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.EntityFramework.Core\n{\n [Startup(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")),Object(i.b)("p",null,"\u5982\u679c\u6709\u591a\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\uff0c",Object(i.b)("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"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"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")),Object(i.b)("h2",{id:"918-\u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61"},"9.1.8 \u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u4e2d\uff0c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u662f\u5b9a\u4e49\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u9879\u76ee\u5c42\uff0c\u5e76\u4e14\u8be5\u5c42\u4e0d\u88ab ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Application")," \u548c ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Core")," \u7b49\u5c42\u5f15\u7528\u3002"),Object(i.b)("p",null,"\u6240\u4ee5\u5c31\u4e0d\u80fd\u76f4\u63a5\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Application")," \u9879\u76ee\u5c42\u76f4\u63a5\u4f7f\u7528 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u5b9a\u4e49\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u3002"),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u4e3a\u4e86\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\uff0c\u63d0\u4f9b\u4e86\u4e24\u79cd\u65b9\u5f0f\u5904\u7406\uff1a"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"respository.DbContext")," \uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61\uff0c\u8fd4\u56de\u662f ",Object(i.b)("inlineCode",{parentName:"li"},"DbContext")," \u62bd\u8c61\u7c7b\u578b"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"respository.DynamicDbContext"),"\uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61\uff0c\u8fd4\u56de\u7684\u662f ",Object(i.b)("inlineCode",{parentName:"li"},"dynamic")," \u7c7b\u578b")),Object(i.b)("p",null,"\u5982\u679c\u4f60\u53ea\u662f\u60f3\u4f7f\u7528 ",Object(i.b)("inlineCode",{parentName:"p"},"DbContext")," \u7684\u529f\u80fd\uff0c\u76f4\u63a5\u4f7f\u7528 ",Object(i.b)("inlineCode",{parentName:"p"},"respository.DbContext")," \u5373\u53ef\uff0c\u5982\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"respository.DbContext.SaveChanges();\n")),Object(i.b)("p",null,"\u5982\u679c\u4f60\u60f3\u80fd\u591f\u83b7\u53d6\u5177\u4f53\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u7c7b\u578b\uff0c\u5982 ",Object(i.b)("inlineCode",{parentName:"p"},"MyDbContext"),"\uff0c\u90a3\u4e48\u4f7f\u7528 ",Object(i.b)("inlineCode",{parentName:"p"},"respository.DynamicDbContext")," \u5c31\u53ef\u4ee5\u83b7\u53d6\u5230\u5177\u4f53\u7684 ",Object(i.b)("inlineCode",{parentName:"p"},"MyDbContext")," \u7c7b\u578b\u3002\u5982\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"var persons = respository.DynamicDbContext.Persons.Find(1);\nvar users = respository.DynamicDbContext.Users;\n")),Object(i.b)("p",null,"\u8fd9\u6837\u5c31\u53ef\u4ee5\u76f4\u63a5\u64cd\u4f5c ",Object(i.b)("inlineCode",{parentName:"p"},"MyDbContext")," \u5b9a\u4e49\u7684\u5c5e\u6027\u548c\u65b9\u6cd5\u4e86\u3002"),Object(i.b)("h2",{id:"919-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.1.9 \u53cd\u9988\u4e0e\u5efa\u8bae"),Object(i.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e0e\u6211\u4eec\u4ea4\u6d41")),Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},"\u7ed9 Fur \u63d0 ",Object(i.b)("a",Object(a.a)({parentName:"p"},{href:"https://gitee.com/monksoul/Fur/issues/new?issue"}),"Issue"),"\u3002"))),Object(i.b)("hr",null),Object(i.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e86\u89e3\u66f4\u591a")),Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},"\u60f3\u4e86\u89e3\u66f4\u591a ",Object(i.b)("inlineCode",{parentName:"p"},"\u6570\u636e\u5e93\u4e0a\u4e0b\u6587")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",Object(i.b)("a",Object(a.a)({parentName:"p"},{href:"https://docs.microsoft.com/zh-cn/ef/core/miscellaneous/configuring-dbcontext"}),"EF Core - \u914d\u7f6e DbContext")," \u7ae0\u8282\u3002"))))}l.isMDXComponent=!0}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[24],{138:function(e,t,n){"use strict";n.d(t,"a",(function(){return d})),n.d(t,"b",(function(){return O}));var a=n(0),r=n.n(a);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 b(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 p=r.a.createContext({}),l=function(e){var t=r.a.useContext(p),n=t;return e&&(n="function"==typeof e?e(t):b(b({},t),e)),n},d=function(e){var t=l(e.components);return r.a.createElement(p.Provider,{value:t},e.children)},s={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},m=r.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,o=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),d=l(n),m=a,O=d["".concat(o,".").concat(m)]||d[m]||s[m]||i;return n?r.a.createElement(O,b(b({ref:t},p),{},{components:n})):r.a.createElement(O,b({ref:t},p))}));function O(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,o=new Array(i);o[0]=m;var b={};for(var c in t)hasOwnProperty.call(t,c)&&(b[c]=t[c]);b.originalType=e,b.mdxType="string"==typeof e?e:a,o[1]=b;for(var p=2;pAppDbContext",id:"912-appdbcontext",children:[]},{value:"9.1.3 AppDbContext \u548c DbContext \u533a\u522b",id:"913-appdbcontext-\u548c-dbcontext-\u533a\u522b",children:[]},{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",children:[{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",children:[]},{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",children:[]}]},{value:"9.1.5 \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32",id:"915-\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32",children:[{value:"9.1.5.1 Startup \u65b9\u5f0f\u914d\u7f6e",id:"9151-startup-\u65b9\u5f0f\u914d\u7f6e",children:[]},{value:"9.1.5.2 [AppDbContext] \u65b9\u5f0f\u914d\u7f6e",id:"9152-appdbcontext-\u65b9\u5f0f\u914d\u7f6e",children:[]},{value:"9.1.5.3 OnConfiguring \u65b9\u5f0f\u914d\u7f6e",id:"9153-onconfiguring-\u65b9\u5f0f\u914d\u7f6e",children:[]}]},{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",children:[]},{value:"9.1.7 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c",id:"917-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c",children:[]},{value:"9.1.8 \u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61",id:"918-\u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61",children:[]},{value:"9.1.9 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"919-\u53cd\u9988\u4e0e\u5efa\u8bae",children:[]}],p={rightToc:c};function l(e){var t=e.components,n=Object(r.a)(e,["components"]);return Object(i.b)("wrapper",Object(a.a)({},p,n,{components:t,mdxType:"MDXLayout"}),Object(i.b)("h2",{id:"911-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.1.1 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(i.b)("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"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u4e2d\uff0c\u9ed8\u8ba4\u96c6\u6210\u4e86\u5fae\u8f6f\u4eb2\u513f\u5b50\uff1a",Object(i.b)("inlineCode",{parentName:"p"},"EntityFramework Core")," \uff0c\u4e5f\u5c31\u662f\u901a\u5e38\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6307\u7684\u662f ",Object(i.b)("inlineCode",{parentName:"p"},"DbContext")," \u7c7b\u6216\u5b83\u7684\u5b9e\u73b0\u7c7b\u3002"),Object(i.b)("h2",{id:"912-appdbcontext"},"9.1.2 ",Object(i.b)("inlineCode",{parentName:"h2"},"AppDbContext")),Object(i.b)("p",null,"\u5728\u6211\u4eec\u5b9e\u9645\u9879\u76ee\u5f00\u53d1\u8fc7\u7a0b\u4e2d\uff0c\u4f7f\u7528 ",Object(i.b)("inlineCode",{parentName:"p"},"EFCore")," \u63d0\u4f9b\u7684 ",Object(i.b)("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"),Object(i.b)("p",null,"\u6240\u4ee5\uff0c",Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u63d0\u4f9b\u4e86 ",Object(i.b)("inlineCode",{parentName:"p"},"AppDbContext")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u8be5\u4e0a\u4e0b\u6587\u7ee7\u627f\u81ea ",Object(i.b)("inlineCode",{parentName:"p"},"DbContext"),"\u3002"),Object(i.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u8bf4\u660e")),Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},"\u540e\u7eed\u7ae0\u8282\uff0c\u7686\u91c7\u7528 ",Object(i.b)("inlineCode",{parentName:"p"},"EFCore")," \u4ee3\u66ff ",Object(i.b)("inlineCode",{parentName:"p"},"EntityFramework Core"),"\u3002"))),Object(i.b)("h2",{id:"913-appdbcontext-\u548c-dbcontext-\u533a\u522b"},"9.1.3 ",Object(i.b)("inlineCode",{parentName:"h2"},"AppDbContext")," \u548c ",Object(i.b)("inlineCode",{parentName:"h2"},"DbContext")," \u533a\u522b"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u7ee7\u627f\u81ea ",Object(i.b)("inlineCode",{parentName:"li"},"DbContext"),"\uff0c\u5177\u5907 ",Object(i.b)("inlineCode",{parentName:"li"},"DbContext")," \u6240\u6709\u529f\u80fd\u3002"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u591a\u6570\u636e\u5e93\u64cd\u4f5c\u6cdb\u578b\u7248\u672c\uff0c\u5982\uff1a",Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u81ea\u52a8\u914d\u7f6e\u5b9e\u4f53\u4fe1\u606f\uff0c\u65e0\u9700\u5728 ",Object(i.b)("inlineCode",{parentName:"li"},"OnModelCreating")," \u4e2d\u914d\u7f6e"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u5185\u7f6e\u591a\u79df\u6237\u652f\u6301"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u5168\u5c40\u6a21\u578b\u914d\u7f6e\u62e6\u622a\u5668"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u652f\u6301\u6570\u636e\u63d0\u4ea4\u66f4\u6539\u591a\u4e2a\u4e8b\u4ef6"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u63d0\u4f9b\u66f4\u52a0\u5f3a\u5927\u7684\u6a21\u578b\u64cd\u4f5c\u80fd\u529b\uff0c\u5982\u679c ",Object(i.b)("inlineCode",{parentName:"li"},"Sql")," \u64cd\u4f5c\uff0c\u8bfb\u5199\u5206\u79bb\u7b49"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u80fd\u591f\u5f97\u5230 ",Object(i.b)("inlineCode",{parentName:"li"},"Fur")," \u6846\u67b6\u66f4\u591a\u7684\u529f\u80fd\u652f\u6301")),Object(i.b)("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"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u4e2d\u4e86\uff0c\u63d0\u4f9b\u4e86\u4e24\u79cd ",Object(i.b)("inlineCode",{parentName:"p"},"AppDbContext")," \u5b9a\u4e49\u65b9\u5f0f\uff1a"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u64cd\u4f5c\u9ed8\u8ba4\u6570\u636e\u5e93"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext")," \u64cd\u4f5c N \u4e2a\u6570\u636e\u5e93")),Object(i.b)("p",null,"\u5176\u4e2d ",Object(i.b)("inlineCode",{parentName:"p"},"AppDbContext")," \u9ed8\u8ba4\u7ee7\u627f\u81ea ",Object(i.b)("inlineCode",{parentName:"p"},"AppDbContext"),"\u3002"),Object(i.b)("p",null,"\u4e0b\u9762\u662f\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u521b\u5efa\u7684\u591a\u4e2a\u4f8b\u5b50\uff1a"),Object(i.b)("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"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{1,6,12}","{1,6,12}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("\u8fde\u63a5\u5b57\u7b26\u4e32\u6216appsetting.json \u952e")]\n public class FurDbContext : AppDbContext // \u7ee7\u627f AppDbContext<> \u7c7b\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(i.b)("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"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{1,6,12}","{1,6,12}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.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')),Object(i.b)("div",{className:"admonition admonition-important alert alert--info"},Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},"\u6240\u6709\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u90fd\u5e94\u8be5\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u9879\u76ee\u4e2d\u521b\u5efa\u3002\u5173\u4e8e ",Object(i.b)("inlineCode",{parentName:"p"},"TDbContextLocator")," \u5c06\u5728\u4e0b\u4e00\u7ae0\u8282 \u300a",Object(i.b)("a",Object(a.a)({parentName:"p"},{href:"dbcontext-locator"}),"9.2 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668"),"\u300b\u9610\u8ff0\u3002"))),Object(i.b)("h2",{id:"915-\u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32"},"9.1.5 \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32"),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u63d0\u4f9b\u591a\u79cd\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u914d\u7f6e\u65b9\u5f0f\uff1a"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"\u5728 ",Object(i.b)("inlineCode",{parentName:"li"},"Startup")," \u4e2d\u6dfb\u52a0\u670d\u52a1\uff1a",Object(i.b)("inlineCode",{parentName:"li"},'AddSqlServerPool("\u8fde\u63a5\u5b57\u7b26\u4e32")')," \u65b9\u5f0f"),Object(i.b)("li",{parentName:"ul"},"\u4f7f\u7528 ",Object(i.b)("inlineCode",{parentName:"li"},'[AppDbContext("\u8fde\u63a5\u5b57\u7b26\u4e32/Key")]')," \u7279\u6027\u65b9\u5f0f\uff08\u53ea\u5728 ",Object(i.b)("inlineCode",{parentName:"li"},"AppDbContext \u5b9e\u73b0\u7c7b\u6709\u6548"),"\uff09",Object(i.b)("strong",{parentName:"li"},"\u63a8\u8350")),Object(i.b)("li",{parentName:"ul"},"\u901a\u8fc7\u91cd\u5199 ",Object(i.b)("inlineCode",{parentName:"li"},"OnConfiguring(DbContextOptionsBuilder optionsBuilder)")," \u914d\u7f6e")),Object(i.b)("h3",{id:"9151-startup-\u65b9\u5f0f\u914d\u7f6e"},"9.1.5.1 ",Object(i.b)("inlineCode",{parentName:"h3"},"Startup")," \u65b9\u5f0f\u914d\u7f6e"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{12-19} title="Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"',"{12-19}":!0,title:'"Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"'}),'using Fur.DependencyInjection;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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, "\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, "\u8fde\u63a5\u5b57\u7b26\u4e32");\n });\n }\n }\n}\n')),Object(i.b)("h3",{id:"9152-appdbcontext-\u65b9\u5f0f\u914d\u7f6e"},"9.1.5.2 ",Object(i.b)("inlineCode",{parentName:"h3"},"[AppDbContext]")," \u65b9\u5f0f\u914d\u7f6e"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{1,6}","{1,6}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("DbConnectionString")] // \u652f\u6301 `appsetting.json` \u540d\u6216 \u8fde\u63a5\u5b57\u7b26\u4e32\n public class FurDbContext : AppDbContext\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(i.b)("div",{className:"admonition admonition-tip alert alert--success"},Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"12",height:"16",viewBox:"0 0 12 16"}),Object(i.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u5c0f\u63d0\u793a")),Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u63a8\u8350\u4f7f\u7528\u6b64\u65b9\u5f0f\u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\u3002"))),Object(i.b)("p",null,Object(i.b)("strong",{parentName:"p"},Object(i.b)("inlineCode",{parentName:"strong"},"[AppDbContext]"))," \u5185\u7f6e\u5c5e\u6027\uff1a"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"ConnectionString"),"\uff1a\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u6216\u914d\u7f6e\u6587\u4ef6\u4e2d\u7684\u8def\u5f84\uff08\u652f\u6301\u81ea\u5b9a\u4e49\u914d\u7f6e\u67e5\u627e\uff09\uff0c\u6216 ",Object(i.b)("inlineCode",{parentName:"li"},"appsetting.json")," \u7684 ",Object(i.b)("inlineCode",{parentName:"li"},"ConnectionStrings")," \u914d\u7f6e\u5b57\u7b26\u4e32"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"TablePrefix"),"\uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u8868\u7edf\u4e00\u524d\u7f00"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"TableSuffix"),"\uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u8868\u7edf\u4e00\u540e\u7f00")),Object(i.b)("h3",{id:"9153-onconfiguring-\u65b9\u5f0f\u914d\u7f6e"},"9.1.5.3 ",Object(i.b)("inlineCode",{parentName:"h3"},"OnConfiguring")," \u65b9\u5f0f\u914d\u7f6e"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{16-20}","{16-20}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n public class FurDbContext : AppDbContext\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurDbContext(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')),Object(i.b)("div",{className:"admonition admonition-important alert alert--info"},Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},"\u8fd9\u4e09\u79cd\u65b9\u5f0f\u53ef\u4ee5\u540c\u65f6\u4f7f\u7528\uff0c\u4f46\u662f\u6709\u4f18\u5148\u7ea7\uff1a",Object(i.b)("inlineCode",{parentName:"p"},"[AppDbContext]")," -> ",Object(i.b)("inlineCode",{parentName:"p"},"Startup")," -> ",Object(i.b)("inlineCode",{parentName:"p"},"OnConfiguring"),"\uff08\u4f4e\u5230\u9ad8\uff09"),Object(i.b)("p",{parentName:"div"},"\u4e5f\u5c31\u662f ",Object(i.b)("inlineCode",{parentName:"p"},"OnConfiguring")," \u914d\u7f6e\u4f1a\u8986\u76d6 ",Object(i.b)("inlineCode",{parentName:"p"},"Startup")," \u914d\u7f6e\uff0c",Object(i.b)("inlineCode",{parentName:"p"},"Startup")," \u914d\u7f6e\u4f1a\u8986\u76d6 ",Object(i.b)("inlineCode",{parentName:"p"},"[AppDbContext]")," \u914d\u7f6e\u6240\u914d\u7f6e\u7684\u8fde\u63a5\u5b57\u7b26\u4e32\u3002"))),Object(i.b)("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"),Object(i.b)("div",{className:"admonition admonition-important alert alert--info"},Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u4e2d\uff0c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u9700\u5b9a\u4e49\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u4e2d\uff0c\u4e14\u6bcf\u4e00\u4e2a\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u90fd\u5fc5\u987b\u62e5\u6709\u552f\u4e00\u7684 ",Object(i.b)("inlineCode",{parentName:"p"},"DbContextLocator")," \u5b9a\u4f4d\u5668"))),Object(i.b)("h2",{id:"917-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c"},"9.1.7 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u6ce8\u518c"),Object(i.b)("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"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{11-13} title="Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"',"{11-13}":!0,title:'"Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"'}),"using Fur.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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")),Object(i.b)("p",null,"\u5982\u679c\u6709\u591a\u4e2a\u6570\u636e\u5e93\u64cd\u4f5c\uff0c",Object(i.b)("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"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"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")),Object(i.b)("h2",{id:"918-\u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61"},"9.1.8 \u52a8\u6001\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u4e2d\uff0c\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u662f\u5b9a\u4e49\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u9879\u76ee\u5c42\uff0c\u5e76\u4e14\u8be5\u5c42\u4e0d\u88ab ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Application")," \u548c ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Core")," \u7b49\u5c42\u5f15\u7528\u3002"),Object(i.b)("p",null,"\u6240\u4ee5\u5c31\u4e0d\u80fd\u76f4\u63a5\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Application")," \u9879\u76ee\u5c42\u76f4\u63a5\u4f7f\u7528 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u5b9a\u4e49\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u3002"),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u4e3a\u4e86\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\uff0c\u63d0\u4f9b\u4e86\u4e24\u79cd\u65b9\u5f0f\u5904\u7406\uff1a"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"respository.DbContext")," \uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61\uff0c\u8fd4\u56de\u662f ",Object(i.b)("inlineCode",{parentName:"li"},"DbContext")," \u62bd\u8c61\u7c7b\u578b"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"respository.DynamicDbContext"),"\uff1a\u5f53\u524d\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5bf9\u8c61\uff0c\u8fd4\u56de\u7684\u662f ",Object(i.b)("inlineCode",{parentName:"li"},"dynamic")," \u7c7b\u578b")),Object(i.b)("p",null,"\u5982\u679c\u4f60\u53ea\u662f\u60f3\u4f7f\u7528 ",Object(i.b)("inlineCode",{parentName:"p"},"DbContext")," \u7684\u529f\u80fd\uff0c\u76f4\u63a5\u4f7f\u7528 ",Object(i.b)("inlineCode",{parentName:"p"},"respository.DbContext")," \u5373\u53ef\uff0c\u5982\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"respository.DbContext.SaveChanges();\n")),Object(i.b)("p",null,"\u5982\u679c\u4f60\u60f3\u80fd\u591f\u83b7\u53d6\u5177\u4f53\u7684\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u7c7b\u578b\uff0c\u5982 ",Object(i.b)("inlineCode",{parentName:"p"},"MyDbContext"),"\uff0c\u90a3\u4e48\u4f7f\u7528 ",Object(i.b)("inlineCode",{parentName:"p"},"respository.DynamicDbContext")," \u5c31\u53ef\u4ee5\u83b7\u53d6\u5230\u5177\u4f53\u7684 ",Object(i.b)("inlineCode",{parentName:"p"},"MyDbContext")," \u7c7b\u578b\u3002\u5982\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"var persons = respository.DynamicDbContext.Persons.Find(1);\nvar users = respository.DynamicDbContext.Users;\n")),Object(i.b)("p",null,"\u8fd9\u6837\u5c31\u53ef\u4ee5\u76f4\u63a5\u64cd\u4f5c ",Object(i.b)("inlineCode",{parentName:"p"},"MyDbContext")," \u5b9a\u4e49\u7684\u5c5e\u6027\u548c\u65b9\u6cd5\u4e86\u3002"),Object(i.b)("h2",{id:"919-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.1.9 \u53cd\u9988\u4e0e\u5efa\u8bae"),Object(i.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e0e\u6211\u4eec\u4ea4\u6d41")),Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},"\u7ed9 Fur \u63d0 ",Object(i.b)("a",Object(a.a)({parentName:"p"},{href:"https://gitee.com/monksoul/Fur/issues/new?issue"}),"Issue"),"\u3002"))),Object(i.b)("hr",null),Object(i.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e86\u89e3\u66f4\u591a")),Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},"\u60f3\u4e86\u89e3\u66f4\u591a ",Object(i.b)("inlineCode",{parentName:"p"},"\u6570\u636e\u5e93\u4e0a\u4e0b\u6587")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",Object(i.b)("a",Object(a.a)({parentName:"p"},{href:"https://docs.microsoft.com/zh-cn/ef/core/miscellaneous/configuring-dbcontext"}),"EF Core - \u914d\u7f6e DbContext")," \u7ae0\u8282\u3002"))))}l.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/404.html b/handbook/build/404.html index 92e999379ce..b41245f00d6 100644 --- a/handbook/build/404.html +++ b/handbook/build/404.html @@ -6,14 +6,14 @@ Page Not Found | Fur - +

    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/4dbcf072.c0f2f064.js b/handbook/build/4dbcf072.19b891a9.js similarity index 54% rename from handbook/build/4dbcf072.c0f2f064.js rename to handbook/build/4dbcf072.19b891a9.js index b354183e3d0..3fc6412b3ea 100644 --- a/handbook/build/4dbcf072.c0f2f064.js +++ b/handbook/build/4dbcf072.19b891a9.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[30],{138:function(e,n,t){"use strict";t.d(n,"a",(function(){return d})),t.d(n,"b",(function(){return u}));var a=t(0),r=t.n(a);function c(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 b(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=r.a.createContext({}),l=function(e){var n=r.a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):b(b({},n),e)),t},d=function(e){var n=l(e.components);return r.a.createElement(s.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.a.createElement(r.a.Fragment,{},n)}},m=r.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,c=e.originalType,i=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),d=l(t),m=a,u=d["".concat(i,".").concat(m)]||d[m]||p[m]||c;return t?r.a.createElement(u,b(b({ref:n},s),{},{components:t})):r.a.createElement(u,b({ref:n},s))}));function u(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var c=t.length,i=new Array(c);i[0]=m;var b={};for(var o in n)hasOwnProperty.call(n,o)&&(b[o]=n[o]);b.originalType=e,b.mdxType="string"==typeof e?e:a,i[1]=b;for(var s=2;sfunction(e,n,t,{forcePrependBaseUrl:a=!1,absolute:c=!1}={}){if(!t)return t;if(t.startsWith("#"))return t;if(Object(r.b)(t))return t;if(a)return n+t;const i=t.startsWith(n)?t:n+t.replace(/^\//,"");return c?e+i:i}(n,e,t,a)}}function i(e,n={}){const{withBaseUrl:t}=c();return t(e,n)}},141:function(e,n,t){"use strict";function a(e){return!0===/^(\w*:|\/\/)/.test(e)}function r(e){return void 0!==e&&!a(e)}t.d(n,"b",(function(){return a})),t.d(n,"a",(function(){return r}))},85:function(e,n,t){"use strict";t.r(n),t.d(n,"frontMatter",(function(){return b})),t.d(n,"metadata",(function(){return o})),t.d(n,"rightToc",(function(){return s})),t.d(n,"default",(function(){return d}));var a=t(2),r=t(6),c=(t(0),t(138)),i=t(140),b={id:"dbcontext-read-write",title:"9.26 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236",sidebar_label:"9.26 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236"},o={unversionedId:"dbcontext-read-write",id:"dbcontext-read-write",isDocsHomePage:!1,title:"9.26 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236",description:"9.26.1 \u8bfb\u5199\u5206\u79bb",source:"@site/docs\\dbcontext-read-write.mdx",slug:"/dbcontext-read-write",permalink:"/fur/docs/dbcontext-read-write",editUrl:"https://gitee.com/monksoul/Fur/tree/main/handbook/docs/dbcontext-read-write.mdx",version:"current",sidebar_label:"9.26 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236",sidebar:"docs",previous:{title:"9.25 \u4e8b\u52a1\u548c\u5de5\u4f5c\u5355\u5143",permalink:"/fur/docs/tran"},next:{title:"9.27 \u5206\u8868\u5206\u5e93",permalink:"/fur/docs/split-db"}},s=[{value:"9.26.1 \u8bfb\u5199\u5206\u79bb",id:"9261-\u8bfb\u5199\u5206\u79bb",children:[{value:"9.26.1.1 \u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898",id:"92611-\u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898",children:[]},{value:"9.26.1.2 \u6ce8\u610f\u4e8b\u9879",id:"92612-\u6ce8\u610f\u4e8b\u9879",children:[]}]},{value:"9.26.2 \u5982\u4f55\u5b9e\u73b0",id:"9262-\u5982\u4f55\u5b9e\u73b0",children:[{value:"9.26.2.1 \u521b\u5efa \u4e3b\u5e93 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"92621-\u521b\u5efa-\u4e3b\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"9.26.2.2 \u521b\u5efa \u4ece\u5e93 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"92622-\u521b\u5efa-\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"9.26.2.3 \u6ce8\u518c \u4e3b\u4ece\u5e93 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"92623-\u6ce8\u518c-\u4e3b\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"9.26.2.4 \u521b\u5efa Person \u5b9e\u4f53",id:"92624-\u521b\u5efa-person-\u5b9e\u4f53",children:[]},{value:"9.26.2.5 \u5c06 Person \u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868",id:"92625-\u5c06-person-\u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868",children:[]},{value:"9.26.2.6 \u4f7f\u7528\u4f8b\u5b50",id:"92626-\u4f7f\u7528\u4f8b\u5b50",children:[]}]},{value:"9.26.3 \u4e3b\u4ece\u590d\u5236",id:"9263-\u4e3b\u4ece\u590d\u5236",children:[]},{value:"9.26.4 \u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f",id:"9264-\u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f",children:[{value:"9.26.4.1 \u540c\u6b65\u590d\u5236",id:"92641-\u540c\u6b65\u590d\u5236",children:[]},{value:"9.26.4.2 \u5f02\u6b65\u590d\u5236",id:"92642-\u5f02\u6b65\u590d\u5236",children:[]},{value:"9.26.4.3 \u534a\u540c\u6b65\u590d\u5236",id:"92643-\u534a\u540c\u6b65\u590d\u5236",children:[]}]},{value:"9.26.5 SqlServer \u4e3b\u5e93\u914d\u7f6e",id:"9265-sqlserver-\u4e3b\u5e93\u914d\u7f6e",children:[{value:"9.26.5.1 \u6dfb\u52a0 \u672c\u5730\u53d1\u5e03",id:"92651-\u6dfb\u52a0-\u672c\u5730\u53d1\u5e03",children:[]},{value:"9.26.5.2 \u9009\u62e9 \u5206\u53d1\u670d\u52a1\u5668",id:"92652-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668",children:[]},{value:"9.26.5.3 \u542f\u7528 \u4ee3\u7406",id:"92653-\u542f\u7528-\u4ee3\u7406",children:[]},{value:"9.26.5.4 \u53d1\u5e03\u6570\u636e\u5e93",id:"92654-\u53d1\u5e03\u6570\u636e\u5e93",children:[]},{value:"9.26.5.5 \u5feb\u7167\u53d1\u5e03",id:"92655-\u5feb\u7167\u53d1\u5e03",children:[]},{value:"9.26.5.6 \u9009\u62e9\u53d1\u5e03\u9879\u76ee",id:"92656-\u9009\u62e9\u53d1\u5e03\u9879\u76ee",children:[]},{value:"9.26.5.7 \u914d\u7f6e\u5206\u53d1\u8ba1\u5212",id:"92657-\u914d\u7f6e\u5206\u53d1\u8ba1\u5212",children:[]},{value:"9.26.5.8 \u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e",id:"92658-\u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e",children:[]},{value:"9.26.5.9 \u5b8c\u6210\u914d\u7f6e",id:"92659-\u5b8c\u6210\u914d\u7f6e",children:[]}]},{value:"9.26.6 SqlServer \u4ece\u5e93\u914d\u7f6e",id:"9266-sqlserver-\u4ece\u5e93\u914d\u7f6e",children:[{value:"9.26.6.1 \u6dfb\u52a0 \u672c\u5730\u8ba2\u9605",id:"92661-\u6dfb\u52a0-\u672c\u5730\u8ba2\u9605",children:[]},{value:"9.26.6.2 \u9009\u62e9 \u5206\u53d1\u670d\u52a1\u5668",id:"92662-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668",children:[]},{value:"9.26.6.3 \u9009\u62e9 \u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e",id:"92663-\u9009\u62e9-\u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e",children:[]},{value:"9.26.6.4 \u9009\u62e9 \u8ba2\u9605\u6570\u636e\u5e93",id:"92664-\u9009\u62e9-\u8ba2\u9605\u6570\u636e\u5e93",children:[]},{value:"9.26.6.5 \u9009\u62e9 \u5206\u53d1\u5b89\u5168\u8bbe\u7f6e",id:"92665-\u9009\u62e9-\u5206\u53d1\u5b89\u5168\u8bbe\u7f6e",children:[]},{value:"9.26.6.6 \u9009\u62e9 \u540c\u6b65\u8ba1\u5212",id:"92666-\u9009\u62e9-\u540c\u6b65\u8ba1\u5212",children:[]},{value:"9.26.6.7 \u5b8c\u6210\u8ba2\u9605",id:"92667-\u5b8c\u6210\u8ba2\u9605",children:[]}]},{value:"9.26.7 \u5206\u53d1\u5b9a\u4e49\u76d1\u89c6",id:"9267-\u5206\u53d1\u5b9a\u4e49\u76d1\u89c6",children:[]},{value:"9.26.8 \u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c",id:"9268-\u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c",children:[]},{value:"9.26.9 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9269-\u53cd\u9988\u4e0e\u5efa\u8bae",children:[]}],l={rightToc:s};function d(e){var n=e.components,t=Object(r.a)(e,["components"]);return Object(c.b)("wrapper",Object(a.a)({},l,t,{components:n,mdxType:"MDXLayout"}),Object(c.b)("h2",{id:"9261-\u8bfb\u5199\u5206\u79bb"},"9.26.1 \u8bfb\u5199\u5206\u79bb"),Object(c.b)("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"),Object(c.b)("img",{src:Object(i.a)("img/readwrite.png"),style:{height:300}}),Object(c.b)("h3",{id:"92611-\u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898"},"9.26.1.1 \u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898"),Object(c.b)("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"),Object(c.b)("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"),Object(c.b)("h3",{id:"92612-\u6ce8\u610f\u4e8b\u9879"},"9.26.1.2 \u6ce8\u610f\u4e8b\u9879"),Object(c.b)("ul",null,Object(c.b)("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"),Object(c.b)("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"),Object(c.b)("li",{parentName:"ul"},"\u4e3b\u4ece\u7684\u4e00\u81f4\u6027\u95ee\u9898\u9700\u8981\u8003\u8651\u3002")),Object(c.b)("h2",{id:"9262-\u5982\u4f55\u5b9e\u73b0"},"9.26.2 \u5982\u4f55\u5b9e\u73b0"),Object(c.b)("p",null,Object(c.b)("inlineCode",{parentName:"p"},"Fur")," \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"),Object(c.b)("p",null,"\u8bfb\u5199\u5206\u79bb\u64cd\u4f5c\u4e3b\u8981\u4f7f\u7528 ",Object(c.b)("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"),Object(c.b)("p",null,"\u4e0b\u9762\u5c31\u7ed9\u5927\u5bb6\u6f14\u793a\u5982\u4f55\u8bfb\u5199\u591a\u5e93\u8bfb\u5199\u64cd\u4f5c\u3002"),Object(c.b)("h3",{id:"92621-\u521b\u5efa-\u4e3b\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.26.2.1 \u521b\u5efa ",Object(c.b)("inlineCode",{parentName:"h3"},"\u4e3b\u5e93")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.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')),Object(c.b)("p",null,Object(c.b)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff1a")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-json"}),'{\n "ConnectionStrings": {\n "MasterConnectionString": "Server=localhost;Database=Fur;User=sa;Password=000000;MultipleActiveResultSets=True;"\n }\n}\n')),Object(c.b)("h3",{id:"92622-\u521b\u5efa-\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.26.2.2 \u521b\u5efa ",Object(c.b)("inlineCode",{parentName:"h3"},"\u4ece\u5e93")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{11}","{11}":!0}),'using Fur.Core;\nusing Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.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')),Object(c.b)("div",{className:"admonition admonition-important alert alert--info"},Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(c.b)("h5",{parentName:"div"},Object(c.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(c.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(c.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(c.b)("p",{parentName:"div"},"\u591a\u6570\u636e\u5e93\u64cd\u4f5c\u9664\u4e86\u9ed8\u8ba4\u6570\u636e\u5e93\u65e0\u9700\u81ea\u5b9a\u4e49 ",Object(c.b)("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 ",Object(c.b)("inlineCode",{parentName:"p"},"SlaveDbContextLocator")))),Object(c.b)("p",null,Object(c.b)("strong",{parentName:"p"},"\u4ece\u5e93\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\uff1a")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{8}","{8}":!0}),"using Fur.DatabaseAccessor;\n\nnamespace Fur.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")),Object(c.b)("p",null,Object(c.b)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff1a")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-json"}),'{\n "ConnectionStrings": {\n "SlaveConnectionString": "Server=localhost;Database=FurSlave;User=sa;Password=000000;MultipleActiveResultSets=True;"\n }\n}\n')),Object(c.b)("h3",{id:"92623-\u6ce8\u518c-\u4e3b\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.26.2.3 \u6ce8\u518c ",Object(c.b)("inlineCode",{parentName:"h3"},"\u4e3b\u4ece\u5e93")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{13-14}","{13-14}":!0}),"using Fur.Core;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.EntityFramework.Core\n{\n [Startup(600)]\n public sealed class FurEntityFrameworkCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddDatabaseAccessor(options =>\n {\n services.AddSqlServerPool();\n services.AddSqlServerPool();\n });\n }\n }\n}\n")),Object(c.b)("h3",{id:"92624-\u521b\u5efa-person-\u5b9e\u4f53"},"9.26.2.4 \u521b\u5efa ",Object(c.b)("inlineCode",{parentName:"h3"},"Person")," \u5b9e\u4f53"),Object(c.b)("p",null,"\u7531\u4e8e ",Object(c.b)("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 ",Object(c.b)("inlineCode",{parentName:"p"},"\u4e3b\u4ece\u5e93"),"\uff1a"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{7}","{7}":!0}),"using Fur.DatabaseAccessor;\nusing System.ComponentModel.DataAnnotations;\nusing System.ComponentModel.DataAnnotations.Schema;\n\nnamespace Fur.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")),Object(c.b)("h3",{id:"92625-\u5c06-person-\u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868"},"9.26.2.5 \u5c06 ",Object(c.b)("inlineCode",{parentName:"h3"},"Person")," \u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868"),Object(c.b)("p",null,Object(c.b)("strong",{parentName:"p"},"\u521b\u5efa\u4e3b\u5e93\u6570\u636e\u5e93\u8868\uff1a")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Add-Migration v0.0.1 -Context MasterDbContext\n")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Update-Database -Context MasterDbContext\n")),Object(c.b)("p",null,Object(c.b)("strong",{parentName:"p"},"\u521b\u5efa\u4ece\u5e93\u6570\u636e\u5e93\u8868\uff1a")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Add-Migration v0.0.1 -Context SlaveDbContext\n")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Update-Database -Context SlaveDbContext\n")),Object(c.b)("img",{src:Object(i.a)("img/readwrite1.png")}),Object(c.b)("img",{src:Object(i.a)("img/readwrite2.png")}),Object(c.b)("h3",{id:"92626-\u4f7f\u7528\u4f8b\u5b50"},"9.26.2.6 \u4f7f\u7528\u4f8b\u5b50"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{13,19,31,40}","{13,19,31,40}":!0}),'using Fur.Core;\nusing Fur.DatabaseAccessor;\nusing Fur.DynamicApiController;\nusing System.Collections.Generic;\n\nnamespace Fur.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();\n }\n }\n}\n')),Object(c.b)("h2",{id:"9263-\u4e3b\u4ece\u590d\u5236"},"9.26.3 \u4e3b\u4ece\u590d\u5236"),Object(c.b)("p",null,"\u4e3b\u4ece\u590d\u5236\uff1a\u662f\u4e00\u79cd\u6570\u636e\u5907\u4efd\u7684\u65b9\u6848\u3002"),Object(c.b)("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",Object(c.b)("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")),Object(c.b)("h2",{id:"9264-\u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f"},"9.26.4 \u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f"),Object(c.b)("h3",{id:"92641-\u540c\u6b65\u590d\u5236"},"9.26.4.1 \u540c\u6b65\u590d\u5236"),Object(c.b)("p",null,"\u6240\u8c13\u7684\u540c\u6b65\u590d\u5236\uff0c\u610f\u601d\u662f ",Object(c.b)("inlineCode",{parentName:"p"},"Master")," \u7684\u53d8\u5316\uff0c\u5fc5\u987b\u7b49\u5f85 ",Object(c.b)("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 ",Object(c.b)("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"),Object(c.b)("h3",{id:"92642-\u5f02\u6b65\u590d\u5236"},"9.26.4.2 \u5f02\u6b65\u590d\u5236"),Object(c.b)("p",null,"\u5982\u540c AJAX \u8bf7\u6c42\u4e00\u6837\u3002",Object(c.b)("inlineCode",{parentName:"p"},"Master")," \u53ea\u9700\u8981\u5b8c\u6210\u81ea\u5df1\u7684\u6570\u636e\u5e93\u64cd\u4f5c\u5373\u53ef\u3002\u81f3\u4e8e ",Object(c.b)("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",Object(c.b)("strong",{parentName:"p"},"\uff08\u63a8\u8350\u65b9\u5f0f\uff09")),Object(c.b)("h3",{id:"92643-\u534a\u540c\u6b65\u590d\u5236"},"9.26.4.3 \u534a\u540c\u6b65\u590d\u5236"),Object(c.b)("p",null,Object(c.b)("inlineCode",{parentName:"p"},"Master")," \u53ea\u4fdd\u8bc1 ",Object(c.b)("inlineCode",{parentName:"p"},"Slaves")," \u4e2d\u7684\u4e00\u4e2a\u64cd\u4f5c\u6210\u529f\uff0c\u5c31\u8fd4\u56de\uff0c\u5176\u4ed6 ",Object(c.b)("inlineCode",{parentName:"p"},"Slave")," \u4e0d\u7ba1\u3002"),Object(c.b)("p",null,"\u4e0b\u9762\u5c06\u4f7f\u7528 ",Object(c.b)("inlineCode",{parentName:"p"},"SqlServer")," \u7b80\u5355\u914d\u7f6e\u4e3b\u4ece\u590d\u5236\u529f\u80fd\u3002"),Object(c.b)("h2",{id:"9265-sqlserver-\u4e3b\u5e93\u914d\u7f6e"},"9.26.5 ",Object(c.b)("inlineCode",{parentName:"h2"},"SqlServer")," \u4e3b\u5e93\u914d\u7f6e"),Object(c.b)("h3",{id:"92651-\u6dfb\u52a0-\u672c\u5730\u53d1\u5e03"},"9.26.5.1 \u6dfb\u52a0 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u672c\u5730\u53d1\u5e03")),Object(c.b)("img",{src:Object(i.a)("img/dbcopy1.png")}),Object(c.b)("h3",{id:"92652-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668"},"9.26.5.2 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u670d\u52a1\u5668")),Object(c.b)("img",{src:Object(i.a)("img/dbcopy2.png")}),Object(c.b)("h3",{id:"92653-\u542f\u7528-\u4ee3\u7406"},"9.26.5.3 \u542f\u7528 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u4ee3\u7406")),Object(c.b)("img",{src:Object(i.a)("img/dbcopy3.png")}),Object(c.b)("h3",{id:"92654-\u53d1\u5e03\u6570\u636e\u5e93"},"9.26.5.4 \u53d1\u5e03\u6570\u636e\u5e93"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy4.png")}),Object(c.b)("h3",{id:"92655-\u5feb\u7167\u53d1\u5e03"},"9.26.5.5 \u5feb\u7167\u53d1\u5e03"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy5.png")}),Object(c.b)("p",null,"\u5177\u4f53\u9009\u62e9\u4f55\u79cd\u53d1\u5e03\u7c7b\u578b\uff0c\u89c6\u5177\u4f53\u4e1a\u52a1\u573a\u666f\u800c\u5b9a\u3002"),Object(c.b)("h3",{id:"92656-\u9009\u62e9\u53d1\u5e03\u9879\u76ee"},"9.26.5.6 \u9009\u62e9\u53d1\u5e03\u9879\u76ee"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy6.png")}),Object(c.b)("h3",{id:"92657-\u914d\u7f6e\u5206\u53d1\u8ba1\u5212"},"9.26.5.7 \u914d\u7f6e\u5206\u53d1\u8ba1\u5212"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy7.png")}),Object(c.b)("img",{src:Object(i.a)("img/dbcopy8.png")}),Object(c.b)("h3",{id:"92658-\u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e"},"9.26.5.8 \u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy9.png")}),Object(c.b)("img",{src:Object(i.a)("img/dbcopy10.png")}),Object(c.b)("h3",{id:"92659-\u5b8c\u6210\u914d\u7f6e"},"9.26.5.9 \u5b8c\u6210\u914d\u7f6e"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy11.png")}),Object(c.b)("img",{src:Object(i.a)("img/dbcopy12.png")}),Object(c.b)("h2",{id:"9266-sqlserver-\u4ece\u5e93\u914d\u7f6e"},"9.26.6 ",Object(c.b)("inlineCode",{parentName:"h2"},"SqlServer")," \u4ece\u5e93\u914d\u7f6e"),Object(c.b)("h3",{id:"92661-\u6dfb\u52a0-\u672c\u5730\u8ba2\u9605"},"9.26.6.1 \u6dfb\u52a0 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u672c\u5730\u8ba2\u9605")),Object(c.b)("img",{src:Object(i.a)("img/dbrece1.png")}),Object(c.b)("h3",{id:"92662-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668"},"9.26.6.2 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u670d\u52a1\u5668")),Object(c.b)("img",{src:Object(i.a)("img/dbrece2.png")}),Object(c.b)("h3",{id:"92663-\u9009\u62e9-\u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e"},"9.26.6.3 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e")),Object(c.b)("img",{src:Object(i.a)("img/dbrece3.png")}),Object(c.b)("h3",{id:"92664-\u9009\u62e9-\u8ba2\u9605\u6570\u636e\u5e93"},"9.26.6.4 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u8ba2\u9605\u6570\u636e\u5e93")),Object(c.b)("img",{src:Object(i.a)("img/dbrece4.png")}),Object(c.b)("h3",{id:"92665-\u9009\u62e9-\u5206\u53d1\u5b89\u5168\u8bbe\u7f6e"},"9.26.6.5 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u5b89\u5168\u8bbe\u7f6e")),Object(c.b)("img",{src:Object(i.a)("img/dbrece5.png")}),Object(c.b)("img",{src:Object(i.a)("img/dbrece6.png")}),Object(c.b)("h3",{id:"92666-\u9009\u62e9-\u540c\u6b65\u8ba1\u5212"},"9.26.6.6 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u540c\u6b65\u8ba1\u5212")),Object(c.b)("img",{src:Object(i.a)("img/dbrece7.png")}),Object(c.b)("h3",{id:"92667-\u5b8c\u6210\u8ba2\u9605"},"9.26.6.7 \u5b8c\u6210\u8ba2\u9605"),Object(c.b)("img",{src:Object(i.a)("img/dbrece8.png")}),Object(c.b)("h2",{id:"9267-\u5206\u53d1\u5b9a\u4e49\u76d1\u89c6"},"9.26.7 \u5206\u53d1\u5b9a\u4e49\u76d1\u89c6"),Object(c.b)("img",{src:Object(i.a)("img/dbrece9.png")}),Object(c.b)("h2",{id:"9268-\u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c"},"9.26.8 \u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c"),Object(c.b)("img",{src:Object(i.a)("img/dbrece10.png")}),Object(c.b)("img",{src:Object(i.a)("img/dbrece11.png")}),Object(c.b)("div",{className:"admonition admonition-important alert alert--info"},Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(c.b)("h5",{parentName:"div"},Object(c.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(c.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(c.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u7279\u6027")),Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(c.b)("p",{parentName:"div"},'\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'))),Object(c.b)("h2",{id:"9269-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.26.9 \u53cd\u9988\u4e0e\u5efa\u8bae"),Object(c.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(c.b)("h5",{parentName:"div"},Object(c.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(c.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(c.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e0e\u6211\u4eec\u4ea4\u6d41")),Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(c.b)("p",{parentName:"div"},"\u7ed9 Fur \u63d0 ",Object(c.b)("a",Object(a.a)({parentName:"p"},{href:"https://gitee.com/monksoul/Fur/issues/new?issue"}),"Issue"),"\u3002"))))}d.isMDXComponent=!0}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[30],{138:function(e,n,t){"use strict";t.d(n,"a",(function(){return d})),t.d(n,"b",(function(){return u}));var a=t(0),r=t.n(a);function c(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 b(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var s=r.a.createContext({}),l=function(e){var n=r.a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):b(b({},n),e)),t},d=function(e){var n=l(e.components);return r.a.createElement(s.Provider,{value:n},e.children)},p={inlineCode:"code",wrapper:function(e){var n=e.children;return r.a.createElement(r.a.Fragment,{},n)}},m=r.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,c=e.originalType,i=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),d=l(t),m=a,u=d["".concat(i,".").concat(m)]||d[m]||p[m]||c;return t?r.a.createElement(u,b(b({ref:n},s),{},{components:t})):r.a.createElement(u,b({ref:n},s))}));function u(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var c=t.length,i=new Array(c);i[0]=m;var b={};for(var o in n)hasOwnProperty.call(n,o)&&(b[o]=n[o]);b.originalType=e,b.mdxType="string"==typeof e?e:a,i[1]=b;for(var s=2;sfunction(e,n,t,{forcePrependBaseUrl:a=!1,absolute:c=!1}={}){if(!t)return t;if(t.startsWith("#"))return t;if(Object(r.b)(t))return t;if(a)return n+t;const i=t.startsWith(n)?t:n+t.replace(/^\//,"");return c?e+i:i}(n,e,t,a)}}function i(e,n={}){const{withBaseUrl:t}=c();return t(e,n)}},141:function(e,n,t){"use strict";function a(e){return!0===/^(\w*:|\/\/)/.test(e)}function r(e){return void 0!==e&&!a(e)}t.d(n,"b",(function(){return a})),t.d(n,"a",(function(){return r}))},85:function(e,n,t){"use strict";t.r(n),t.d(n,"frontMatter",(function(){return b})),t.d(n,"metadata",(function(){return o})),t.d(n,"rightToc",(function(){return s})),t.d(n,"default",(function(){return d}));var a=t(2),r=t(6),c=(t(0),t(138)),i=t(140),b={id:"dbcontext-read-write",title:"9.26 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236",sidebar_label:"9.26 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236"},o={unversionedId:"dbcontext-read-write",id:"dbcontext-read-write",isDocsHomePage:!1,title:"9.26 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236",description:"9.26.1 \u8bfb\u5199\u5206\u79bb",source:"@site/docs\\dbcontext-read-write.mdx",slug:"/dbcontext-read-write",permalink:"/fur/docs/dbcontext-read-write",editUrl:"https://gitee.com/monksoul/Fur/tree/main/handbook/docs/dbcontext-read-write.mdx",version:"current",sidebar_label:"9.26 \u8bfb\u5199\u5206\u79bb/\u4e3b\u4ece\u590d\u5236",sidebar:"docs",previous:{title:"9.25 \u4e8b\u52a1\u548c\u5de5\u4f5c\u5355\u5143",permalink:"/fur/docs/tran"},next:{title:"9.27 \u5206\u8868\u5206\u5e93",permalink:"/fur/docs/split-db"}},s=[{value:"9.26.1 \u8bfb\u5199\u5206\u79bb",id:"9261-\u8bfb\u5199\u5206\u79bb",children:[{value:"9.26.1.1 \u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898",id:"92611-\u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898",children:[]},{value:"9.26.1.2 \u6ce8\u610f\u4e8b\u9879",id:"92612-\u6ce8\u610f\u4e8b\u9879",children:[]}]},{value:"9.26.2 \u5982\u4f55\u5b9e\u73b0",id:"9262-\u5982\u4f55\u5b9e\u73b0",children:[{value:"9.26.2.1 \u521b\u5efa \u4e3b\u5e93 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"92621-\u521b\u5efa-\u4e3b\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"9.26.2.2 \u521b\u5efa \u4ece\u5e93 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"92622-\u521b\u5efa-\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"9.26.2.3 \u6ce8\u518c \u4e3b\u4ece\u5e93 \u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"92623-\u6ce8\u518c-\u4e3b\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"9.26.2.4 \u521b\u5efa Person \u5b9e\u4f53",id:"92624-\u521b\u5efa-person-\u5b9e\u4f53",children:[]},{value:"9.26.2.5 \u5c06 Person \u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868",id:"92625-\u5c06-person-\u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868",children:[]},{value:"9.26.2.6 \u4f7f\u7528\u4f8b\u5b50",id:"92626-\u4f7f\u7528\u4f8b\u5b50",children:[]}]},{value:"9.26.3 \u4e3b\u4ece\u590d\u5236",id:"9263-\u4e3b\u4ece\u590d\u5236",children:[]},{value:"9.26.4 \u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f",id:"9264-\u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f",children:[{value:"9.26.4.1 \u540c\u6b65\u590d\u5236",id:"92641-\u540c\u6b65\u590d\u5236",children:[]},{value:"9.26.4.2 \u5f02\u6b65\u590d\u5236",id:"92642-\u5f02\u6b65\u590d\u5236",children:[]},{value:"9.26.4.3 \u534a\u540c\u6b65\u590d\u5236",id:"92643-\u534a\u540c\u6b65\u590d\u5236",children:[]}]},{value:"9.26.5 SqlServer \u4e3b\u5e93\u914d\u7f6e",id:"9265-sqlserver-\u4e3b\u5e93\u914d\u7f6e",children:[{value:"9.26.5.1 \u6dfb\u52a0 \u672c\u5730\u53d1\u5e03",id:"92651-\u6dfb\u52a0-\u672c\u5730\u53d1\u5e03",children:[]},{value:"9.26.5.2 \u9009\u62e9 \u5206\u53d1\u670d\u52a1\u5668",id:"92652-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668",children:[]},{value:"9.26.5.3 \u542f\u7528 \u4ee3\u7406",id:"92653-\u542f\u7528-\u4ee3\u7406",children:[]},{value:"9.26.5.4 \u53d1\u5e03\u6570\u636e\u5e93",id:"92654-\u53d1\u5e03\u6570\u636e\u5e93",children:[]},{value:"9.26.5.5 \u5feb\u7167\u53d1\u5e03",id:"92655-\u5feb\u7167\u53d1\u5e03",children:[]},{value:"9.26.5.6 \u9009\u62e9\u53d1\u5e03\u9879\u76ee",id:"92656-\u9009\u62e9\u53d1\u5e03\u9879\u76ee",children:[]},{value:"9.26.5.7 \u914d\u7f6e\u5206\u53d1\u8ba1\u5212",id:"92657-\u914d\u7f6e\u5206\u53d1\u8ba1\u5212",children:[]},{value:"9.26.5.8 \u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e",id:"92658-\u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e",children:[]},{value:"9.26.5.9 \u5b8c\u6210\u914d\u7f6e",id:"92659-\u5b8c\u6210\u914d\u7f6e",children:[]}]},{value:"9.26.6 SqlServer \u4ece\u5e93\u914d\u7f6e",id:"9266-sqlserver-\u4ece\u5e93\u914d\u7f6e",children:[{value:"9.26.6.1 \u6dfb\u52a0 \u672c\u5730\u8ba2\u9605",id:"92661-\u6dfb\u52a0-\u672c\u5730\u8ba2\u9605",children:[]},{value:"9.26.6.2 \u9009\u62e9 \u5206\u53d1\u670d\u52a1\u5668",id:"92662-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668",children:[]},{value:"9.26.6.3 \u9009\u62e9 \u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e",id:"92663-\u9009\u62e9-\u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e",children:[]},{value:"9.26.6.4 \u9009\u62e9 \u8ba2\u9605\u6570\u636e\u5e93",id:"92664-\u9009\u62e9-\u8ba2\u9605\u6570\u636e\u5e93",children:[]},{value:"9.26.6.5 \u9009\u62e9 \u5206\u53d1\u5b89\u5168\u8bbe\u7f6e",id:"92665-\u9009\u62e9-\u5206\u53d1\u5b89\u5168\u8bbe\u7f6e",children:[]},{value:"9.26.6.6 \u9009\u62e9 \u540c\u6b65\u8ba1\u5212",id:"92666-\u9009\u62e9-\u540c\u6b65\u8ba1\u5212",children:[]},{value:"9.26.6.7 \u5b8c\u6210\u8ba2\u9605",id:"92667-\u5b8c\u6210\u8ba2\u9605",children:[]}]},{value:"9.26.7 \u5206\u53d1\u5b9a\u4e49\u76d1\u89c6",id:"9267-\u5206\u53d1\u5b9a\u4e49\u76d1\u89c6",children:[]},{value:"9.26.8 \u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c",id:"9268-\u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c",children:[]},{value:"9.26.9 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9269-\u53cd\u9988\u4e0e\u5efa\u8bae",children:[]}],l={rightToc:s};function d(e){var n=e.components,t=Object(r.a)(e,["components"]);return Object(c.b)("wrapper",Object(a.a)({},l,t,{components:n,mdxType:"MDXLayout"}),Object(c.b)("h2",{id:"9261-\u8bfb\u5199\u5206\u79bb"},"9.26.1 \u8bfb\u5199\u5206\u79bb"),Object(c.b)("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"),Object(c.b)("img",{src:Object(i.a)("img/readwrite.png"),style:{height:300}}),Object(c.b)("h3",{id:"92611-\u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898"},"9.26.1.1 \u89e3\u51b3\u4e86\u4ec0\u4e48\u95ee\u9898"),Object(c.b)("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"),Object(c.b)("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"),Object(c.b)("h3",{id:"92612-\u6ce8\u610f\u4e8b\u9879"},"9.26.1.2 \u6ce8\u610f\u4e8b\u9879"),Object(c.b)("ul",null,Object(c.b)("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"),Object(c.b)("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"),Object(c.b)("li",{parentName:"ul"},"\u4e3b\u4ece\u7684\u4e00\u81f4\u6027\u95ee\u9898\u9700\u8981\u8003\u8651\u3002")),Object(c.b)("h2",{id:"9262-\u5982\u4f55\u5b9e\u73b0"},"9.26.2 \u5982\u4f55\u5b9e\u73b0"),Object(c.b)("p",null,Object(c.b)("inlineCode",{parentName:"p"},"Fur")," \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"),Object(c.b)("p",null,"\u8bfb\u5199\u5206\u79bb\u64cd\u4f5c\u4e3b\u8981\u4f7f\u7528 ",Object(c.b)("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"),Object(c.b)("p",null,"\u4e0b\u9762\u5c31\u7ed9\u5927\u5bb6\u6f14\u793a\u5982\u4f55\u8bfb\u5199\u591a\u5e93\u8bfb\u5199\u64cd\u4f5c\u3002"),Object(c.b)("h3",{id:"92621-\u521b\u5efa-\u4e3b\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.26.2.1 \u521b\u5efa ",Object(c.b)("inlineCode",{parentName:"h3"},"\u4e3b\u5e93")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.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')),Object(c.b)("p",null,Object(c.b)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff1a")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-json"}),'{\n "ConnectionStrings": {\n "MasterConnectionString": "Server=localhost;Database=Fur;User=sa;Password=000000;MultipleActiveResultSets=True;"\n }\n}\n')),Object(c.b)("h3",{id:"92622-\u521b\u5efa-\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.26.2.2 \u521b\u5efa ",Object(c.b)("inlineCode",{parentName:"h3"},"\u4ece\u5e93")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{11}","{11}":!0}),'using Fur.Core;\nusing Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.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')),Object(c.b)("div",{className:"admonition admonition-important alert alert--info"},Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(c.b)("h5",{parentName:"div"},Object(c.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(c.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(c.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u6ce8\u610f")),Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(c.b)("p",{parentName:"div"},"\u591a\u6570\u636e\u5e93\u64cd\u4f5c\u9664\u4e86\u9ed8\u8ba4\u6570\u636e\u5e93\u65e0\u9700\u81ea\u5b9a\u4e49 ",Object(c.b)("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 ",Object(c.b)("inlineCode",{parentName:"p"},"SlaveDbContextLocator")))),Object(c.b)("p",null,Object(c.b)("strong",{parentName:"p"},"\u4ece\u5e93\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u5b9a\u4f4d\u5668\uff1a")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{8}","{8}":!0}),"using Fur.DatabaseAccessor;\n\nnamespace Fur.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")),Object(c.b)("p",null,Object(c.b)("strong",{parentName:"p"},"\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff1a")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-json"}),'{\n "ConnectionStrings": {\n "SlaveConnectionString": "Server=localhost;Database=FurSlave;User=sa;Password=000000;MultipleActiveResultSets=True;"\n }\n}\n')),Object(c.b)("h3",{id:"92623-\u6ce8\u518c-\u4e3b\u4ece\u5e93-\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"9.26.2.3 \u6ce8\u518c ",Object(c.b)("inlineCode",{parentName:"h3"},"\u4e3b\u4ece\u5e93")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{13-14}","{13-14}":!0}),"using Fur.Core;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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.AddSqlServerPool();\n services.AddSqlServerPool();\n });\n }\n }\n}\n")),Object(c.b)("h3",{id:"92624-\u521b\u5efa-person-\u5b9e\u4f53"},"9.26.2.4 \u521b\u5efa ",Object(c.b)("inlineCode",{parentName:"h3"},"Person")," \u5b9e\u4f53"),Object(c.b)("p",null,"\u7531\u4e8e ",Object(c.b)("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 ",Object(c.b)("inlineCode",{parentName:"p"},"\u4e3b\u4ece\u5e93"),"\uff1a"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{7}","{7}":!0}),"using Fur.DatabaseAccessor;\nusing System.ComponentModel.DataAnnotations;\nusing System.ComponentModel.DataAnnotations.Schema;\n\nnamespace Fur.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")),Object(c.b)("h3",{id:"92625-\u5c06-person-\u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868"},"9.26.2.5 \u5c06 ",Object(c.b)("inlineCode",{parentName:"h3"},"Person")," \u8f6c\u6362\u6210\u6570\u636e\u5e93\u8868"),Object(c.b)("p",null,Object(c.b)("strong",{parentName:"p"},"\u521b\u5efa\u4e3b\u5e93\u6570\u636e\u5e93\u8868\uff1a")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Add-Migration v0.0.1 -Context MasterDbContext\n")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Update-Database -Context MasterDbContext\n")),Object(c.b)("p",null,Object(c.b)("strong",{parentName:"p"},"\u521b\u5efa\u4ece\u5e93\u6570\u636e\u5e93\u8868\uff1a")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Add-Migration v0.0.1 -Context SlaveDbContext\n")),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-shell"}),"Update-Database -Context SlaveDbContext\n")),Object(c.b)("img",{src:Object(i.a)("img/readwrite1.png")}),Object(c.b)("img",{src:Object(i.a)("img/readwrite2.png")}),Object(c.b)("h3",{id:"92626-\u4f7f\u7528\u4f8b\u5b50"},"9.26.2.6 \u4f7f\u7528\u4f8b\u5b50"),Object(c.b)("pre",null,Object(c.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{13,19,31,40}","{13,19,31,40}":!0}),'using Fur.Core;\nusing Fur.DatabaseAccessor;\nusing Fur.DynamicApiController;\nusing System.Collections.Generic;\n\nnamespace Fur.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();\n }\n }\n}\n')),Object(c.b)("h2",{id:"9263-\u4e3b\u4ece\u590d\u5236"},"9.26.3 \u4e3b\u4ece\u590d\u5236"),Object(c.b)("p",null,"\u4e3b\u4ece\u590d\u5236\uff1a\u662f\u4e00\u79cd\u6570\u636e\u5907\u4efd\u7684\u65b9\u6848\u3002"),Object(c.b)("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",Object(c.b)("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")),Object(c.b)("h2",{id:"9264-\u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f"},"9.26.4 \u4e3b\u4ece\u590d\u5236\u51e0\u79cd\u65b9\u5f0f"),Object(c.b)("h3",{id:"92641-\u540c\u6b65\u590d\u5236"},"9.26.4.1 \u540c\u6b65\u590d\u5236"),Object(c.b)("p",null,"\u6240\u8c13\u7684\u540c\u6b65\u590d\u5236\uff0c\u610f\u601d\u662f ",Object(c.b)("inlineCode",{parentName:"p"},"Master")," \u7684\u53d8\u5316\uff0c\u5fc5\u987b\u7b49\u5f85 ",Object(c.b)("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 ",Object(c.b)("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"),Object(c.b)("h3",{id:"92642-\u5f02\u6b65\u590d\u5236"},"9.26.4.2 \u5f02\u6b65\u590d\u5236"),Object(c.b)("p",null,"\u5982\u540c AJAX \u8bf7\u6c42\u4e00\u6837\u3002",Object(c.b)("inlineCode",{parentName:"p"},"Master")," \u53ea\u9700\u8981\u5b8c\u6210\u81ea\u5df1\u7684\u6570\u636e\u5e93\u64cd\u4f5c\u5373\u53ef\u3002\u81f3\u4e8e ",Object(c.b)("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",Object(c.b)("strong",{parentName:"p"},"\uff08\u63a8\u8350\u65b9\u5f0f\uff09")),Object(c.b)("h3",{id:"92643-\u534a\u540c\u6b65\u590d\u5236"},"9.26.4.3 \u534a\u540c\u6b65\u590d\u5236"),Object(c.b)("p",null,Object(c.b)("inlineCode",{parentName:"p"},"Master")," \u53ea\u4fdd\u8bc1 ",Object(c.b)("inlineCode",{parentName:"p"},"Slaves")," \u4e2d\u7684\u4e00\u4e2a\u64cd\u4f5c\u6210\u529f\uff0c\u5c31\u8fd4\u56de\uff0c\u5176\u4ed6 ",Object(c.b)("inlineCode",{parentName:"p"},"Slave")," \u4e0d\u7ba1\u3002"),Object(c.b)("p",null,"\u4e0b\u9762\u5c06\u4f7f\u7528 ",Object(c.b)("inlineCode",{parentName:"p"},"SqlServer")," \u7b80\u5355\u914d\u7f6e\u4e3b\u4ece\u590d\u5236\u529f\u80fd\u3002"),Object(c.b)("h2",{id:"9265-sqlserver-\u4e3b\u5e93\u914d\u7f6e"},"9.26.5 ",Object(c.b)("inlineCode",{parentName:"h2"},"SqlServer")," \u4e3b\u5e93\u914d\u7f6e"),Object(c.b)("h3",{id:"92651-\u6dfb\u52a0-\u672c\u5730\u53d1\u5e03"},"9.26.5.1 \u6dfb\u52a0 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u672c\u5730\u53d1\u5e03")),Object(c.b)("img",{src:Object(i.a)("img/dbcopy1.png")}),Object(c.b)("h3",{id:"92652-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668"},"9.26.5.2 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u670d\u52a1\u5668")),Object(c.b)("img",{src:Object(i.a)("img/dbcopy2.png")}),Object(c.b)("h3",{id:"92653-\u542f\u7528-\u4ee3\u7406"},"9.26.5.3 \u542f\u7528 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u4ee3\u7406")),Object(c.b)("img",{src:Object(i.a)("img/dbcopy3.png")}),Object(c.b)("h3",{id:"92654-\u53d1\u5e03\u6570\u636e\u5e93"},"9.26.5.4 \u53d1\u5e03\u6570\u636e\u5e93"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy4.png")}),Object(c.b)("h3",{id:"92655-\u5feb\u7167\u53d1\u5e03"},"9.26.5.5 \u5feb\u7167\u53d1\u5e03"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy5.png")}),Object(c.b)("p",null,"\u5177\u4f53\u9009\u62e9\u4f55\u79cd\u53d1\u5e03\u7c7b\u578b\uff0c\u89c6\u5177\u4f53\u4e1a\u52a1\u573a\u666f\u800c\u5b9a\u3002"),Object(c.b)("h3",{id:"92656-\u9009\u62e9\u53d1\u5e03\u9879\u76ee"},"9.26.5.6 \u9009\u62e9\u53d1\u5e03\u9879\u76ee"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy6.png")}),Object(c.b)("h3",{id:"92657-\u914d\u7f6e\u5206\u53d1\u8ba1\u5212"},"9.26.5.7 \u914d\u7f6e\u5206\u53d1\u8ba1\u5212"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy7.png")}),Object(c.b)("img",{src:Object(i.a)("img/dbcopy8.png")}),Object(c.b)("h3",{id:"92658-\u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e"},"9.26.5.8 \u914d\u7f6e\u5b89\u5168\u8bbe\u7f6e"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy9.png")}),Object(c.b)("img",{src:Object(i.a)("img/dbcopy10.png")}),Object(c.b)("h3",{id:"92659-\u5b8c\u6210\u914d\u7f6e"},"9.26.5.9 \u5b8c\u6210\u914d\u7f6e"),Object(c.b)("img",{src:Object(i.a)("img/dbcopy11.png")}),Object(c.b)("img",{src:Object(i.a)("img/dbcopy12.png")}),Object(c.b)("h2",{id:"9266-sqlserver-\u4ece\u5e93\u914d\u7f6e"},"9.26.6 ",Object(c.b)("inlineCode",{parentName:"h2"},"SqlServer")," \u4ece\u5e93\u914d\u7f6e"),Object(c.b)("h3",{id:"92661-\u6dfb\u52a0-\u672c\u5730\u8ba2\u9605"},"9.26.6.1 \u6dfb\u52a0 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u672c\u5730\u8ba2\u9605")),Object(c.b)("img",{src:Object(i.a)("img/dbrece1.png")}),Object(c.b)("h3",{id:"92662-\u9009\u62e9-\u5206\u53d1\u670d\u52a1\u5668"},"9.26.6.2 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u670d\u52a1\u5668")),Object(c.b)("img",{src:Object(i.a)("img/dbrece2.png")}),Object(c.b)("h3",{id:"92663-\u9009\u62e9-\u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e"},"9.26.6.3 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u4ee3\u7406\u4f4d\u7f6e")),Object(c.b)("img",{src:Object(i.a)("img/dbrece3.png")}),Object(c.b)("h3",{id:"92664-\u9009\u62e9-\u8ba2\u9605\u6570\u636e\u5e93"},"9.26.6.4 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u8ba2\u9605\u6570\u636e\u5e93")),Object(c.b)("img",{src:Object(i.a)("img/dbrece4.png")}),Object(c.b)("h3",{id:"92665-\u9009\u62e9-\u5206\u53d1\u5b89\u5168\u8bbe\u7f6e"},"9.26.6.5 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u5206\u53d1\u5b89\u5168\u8bbe\u7f6e")),Object(c.b)("img",{src:Object(i.a)("img/dbrece5.png")}),Object(c.b)("img",{src:Object(i.a)("img/dbrece6.png")}),Object(c.b)("h3",{id:"92666-\u9009\u62e9-\u540c\u6b65\u8ba1\u5212"},"9.26.6.6 \u9009\u62e9 ",Object(c.b)("inlineCode",{parentName:"h3"},"\u540c\u6b65\u8ba1\u5212")),Object(c.b)("img",{src:Object(i.a)("img/dbrece7.png")}),Object(c.b)("h3",{id:"92667-\u5b8c\u6210\u8ba2\u9605"},"9.26.6.7 \u5b8c\u6210\u8ba2\u9605"),Object(c.b)("img",{src:Object(i.a)("img/dbrece8.png")}),Object(c.b)("h2",{id:"9267-\u5206\u53d1\u5b9a\u4e49\u76d1\u89c6"},"9.26.7 \u5206\u53d1\u5b9a\u4e49\u76d1\u89c6"),Object(c.b)("img",{src:Object(i.a)("img/dbrece9.png")}),Object(c.b)("h2",{id:"9268-\u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c"},"9.26.8 \u67e5\u770b\u4e3b\u4ece\u590d\u5236\u7ed3\u679c"),Object(c.b)("img",{src:Object(i.a)("img/dbrece10.png")}),Object(c.b)("img",{src:Object(i.a)("img/dbrece11.png")}),Object(c.b)("div",{className:"admonition admonition-important alert alert--info"},Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(c.b)("h5",{parentName:"div"},Object(c.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(c.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(c.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u7279\u6027")),Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(c.b)("p",{parentName:"div"},'\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'))),Object(c.b)("h2",{id:"9269-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.26.9 \u53cd\u9988\u4e0e\u5efa\u8bae"),Object(c.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(c.b)("h5",{parentName:"div"},Object(c.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(c.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(c.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e0e\u6211\u4eec\u4ea4\u6d41")),Object(c.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(c.b)("p",{parentName:"div"},"\u7ed9 Fur \u63d0 ",Object(c.b)("a",Object(a.a)({parentName:"p"},{href:"https://gitee.com/monksoul/Fur/issues/new?issue"}),"Issue"),"\u3002"))))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/5ce0ebbd.355b0f5e.js b/handbook/build/5ce0ebbd.355b0f5e.js new file mode 100644 index 00000000000..a329d3474a6 --- /dev/null +++ b/handbook/build/5ce0ebbd.355b0f5e.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[35],{138:function(e,n,t){"use strict";t.d(n,"a",(function(){return s})),t.d(n,"b",(function(){return j}));var a=t(0),r=t.n(a);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 p(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 c(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 b=r.a.createContext({}),l=function(e){var n=r.a.useContext(b),t=n;return e&&(t="function"==typeof e?e(n):c(c({},n),e)),t},s=function(e){var n=l(e.components);return r.a.createElement(b.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return r.a.createElement(r.a.Fragment,{},n)}},d=r.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,i=e.originalType,p=e.parentName,b=o(e,["components","mdxType","originalType","parentName"]),s=l(t),d=a,j=s["".concat(p,".").concat(d)]||s[d]||u[d]||i;return t?r.a.createElement(j,c(c({ref:n},b),{},{components:t})):r.a.createElement(j,c({ref:n},b))}));function j(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var i=t.length,p=new Array(i);p[0]=d;var c={};for(var o in n)hasOwnProperty.call(n,o)&&(c[o]=n[o]);c.originalType=e,c.mdxType="string"==typeof e?e:a,p[1]=c;for(var b=2;bStartup \u7c7b",id:"31-startup-\u7c7b",children:[{value:"3.1.1 Startup \u4e24\u4e2a\u91cd\u8981\u65b9\u6cd5",id:"311-startup-\u4e24\u4e2a\u91cd\u8981\u65b9\u6cd5",children:[]}]},{value:"3.2 AppStartup",id:"32-appstartup",children:[{value:"3.2.1 \u5982\u4f55\u914d\u7f6e AppStartup",id:"321-\u5982\u4f55\u914d\u7f6e-appstartup",children:[]},{value:"3.2.2 AppStartup \u7ea6\u5b9a",id:"322-appstartup-\u7ea6\u5b9a",children:[]},{value:"3.2.3 AppStartup \u914d\u7f6e\u987a\u5e8f",id:"323-appstartup-\u914d\u7f6e\u987a\u5e8f",children:[]},{value:"3.2.4 AppStartup \u65b9\u6cd5\u8c03\u7528\u987a\u5e8f",id:"324-appstartup-\u65b9\u6cd5\u8c03\u7528\u987a\u5e8f",children:[]}]},{value:"3.3 \u6846\u67b6\u9ed8\u8ba4 AppStartup \u5b9e\u73b0",id:"33-\u6846\u67b6\u9ed8\u8ba4-appstartup-\u5b9e\u73b0",children:[]},{value:"3.4 Startup \u914d\u7f6e\u6700\u4f73\u5b9e\u8df5",id:"34-startup-\u914d\u7f6e\u6700\u4f73\u5b9e\u8df5",children:[]},{value:"3.5 \u5173\u4e8e appsettings.json",id:"35-\u5173\u4e8e-appsettingsjson",children:[]},{value:"3.6 \u795e\u5947\u7684 Inject()",id:"36-\u795e\u5947\u7684-inject",children:[]},{value:"3.7 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"37-\u53cd\u9988\u4e0e\u5efa\u8bae",children:[]}],b={rightToc:o};function l(e){var n=e.components,t=Object(r.a)(e,["components"]);return Object(i.b)("wrapper",Object(a.a)({},b,t,{components:n,mdxType:"MDXLayout"}),Object(i.b)("h2",{id:"31-startup-\u7c7b"},"3.1 ",Object(i.b)("inlineCode",{parentName:"h2"},"Startup")," \u7c7b"),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"Startup")," \u7c7b\u662f ",Object(i.b)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u5e94\u7528\u7a0b\u5e8f\u542f\u52a8\u9ed8\u8ba4\u8c03\u7528\u7684\u7c7b\uff0c\u8be5\u7c7b\u662f\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Program.cs")," \u4e2d\u914d\u7f6e\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{19} title="Fur.Web.Entry\\Program.cs"',"{19}":!0,title:'"Fur.Web.Entry\\Program.cs"'}),"using Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Hosting;\n\nnamespace Fur.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")),Object(i.b)("h3",{id:"311-startup-\u4e24\u4e2a\u91cd\u8981\u65b9\u6cd5"},"3.1.1 ",Object(i.b)("inlineCode",{parentName:"h3"},"Startup")," \u4e24\u4e2a\u91cd\u8981\u65b9\u6cd5"),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"Startup")," \u9ed8\u8ba4\u6709\u4e24\u4e2a\u91cd\u8981\u7684\u65b9\u6cd5:"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("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"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"Configure"),"\uff1a\u914d\u7f6e\u5e94\u7528\u8bf7\u6c42\u5904\u7406\u7ba1\u9053")),Object(i.b)("p",null,"\u9ed8\u8ba4\u4ee3\u7801\u5982\u4e0b\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'{9,13} title="Fur.Web.Entry\\Startup.cs"',"{9,13}":!0,title:'"Fur.Web.Entry\\Startup.cs"'}),"using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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")),Object(i.b)("p",null,"\u5728\u8fd9\u91cc\uff0c\u4e0d\u6253\u7b97\u8be6\u7ec6\u8bb2 ",Object(i.b)("inlineCode",{parentName:"p"},"Startup")," \u7c7b\u7684\u5177\u4f53\u529f\u80fd\u548c\u4f5c\u7528\u3002"),Object(i.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e86\u89e3\u66f4\u591a")),Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},"\u60f3\u4e86\u89e3\u66f4\u591a ",Object(i.b)("inlineCode",{parentName:"p"},"Startup")," \u77e5\u8bc6\u53ef\u67e5\u9605 ",Object(i.b)("a",Object(a.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"))),Object(i.b)("h2",{id:"32-appstartup"},"3.2 ",Object(i.b)("inlineCode",{parentName:"h2"},"AppStartup")),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u4e2d\uff0c\u63d0\u4f9b\u4e86\u66f4\u4e3a\u7075\u6d3b\u7684 ",Object(i.b)("inlineCode",{parentName:"p"},"Startup")," \u7c7b\u914d\u7f6e\u65b9\u5f0f\uff0c\u65e0\u9700\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Web \u542f\u7528\u5c42")," \u4e2d\u914d\u7f6e\uff0c\u53ef\u5c06\u914d\u7f6e\u653e\u5230\u4efb\u4f55\u9879\u76ee\u5c42\u3002"),Object(i.b)("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"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"Startup")," \u7c7b\u9ed8\u8ba4\u548c ",Object(i.b)("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 ",Object(i.b)("inlineCode",{parentName:"li"},"Web \u5e94\u7528\u5c42"),"\uff0c",Object(i.b)("inlineCode",{parentName:"li"},"Startup")," \u53c8\u8981\u91cd\u65b0\u914d\u7f6e"),Object(i.b)("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 ",Object(i.b)("inlineCode",{parentName:"li"},"Startup")," \u7c7b\u5c31\u4f1a\u53d8\u5f97\u8d8a\u6765\u8d8a\u81c3\u80bf\uff0c\u96be\u4ee5\u7ef4\u62a4"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"Startup")," \u7c7b\u65e0\u6cd5\u5176\u4ed6\u9879\u76ee\u7c7b\u578b\u8fdb\u884c\u5171\u7528")),Object(i.b)("p",null,"\u6240\u4ee5\uff0c",Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u63d0\u4f9b\u4e86\u66f4\u52a0\u7075\u6d3b\u7684\u914d\u7f6e\u65b9\u5f0f\uff1a",Object(i.b)("inlineCode",{parentName:"p"},"AppStartup"),"\u3002"),Object(i.b)("h3",{id:"321-\u5982\u4f55\u914d\u7f6e-appstartup"},"3.2.1 \u5982\u4f55\u914d\u7f6e ",Object(i.b)("inlineCode",{parentName:"h3"},"AppStartup")),Object(i.b)("p",null,Object(i.b)("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"),Object(i.b)("h3",{id:"322-appstartup-\u7ea6\u5b9a"},"3.2.2 ",Object(i.b)("inlineCode",{parentName:"h3"},"AppStartup")," \u7ea6\u5b9a"),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"AppStartup")," \u6d3e\u751f\u7c7b\u53ea\u6709\u4e24\u4e2a\u5c0f\u7ea6\u5b9a\uff1a"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"\u4efb\u4f55\u516c\u5f00\u3001\u975e\u9759\u6001\u3001\u8fd4\u56de\u503c\u4e3a ",Object(i.b)("inlineCode",{parentName:"li"},"void")," \u4e14\u65b9\u6cd5\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f ",Object(i.b)("inlineCode",{parentName:"li"},"IServiceCollection")," \u7c7b\u578b\uff0c\u90a3\u4e48\u4ed6\u5c31\u662f\u4e00\u4e2a ",Object(i.b)("inlineCode",{parentName:"li"},"ConfigureServices")," \u65b9\u6cd5"),Object(i.b)("li",{parentName:"ul"},"\u4efb\u4f55\u516c\u5f00\u3001\u975e\u9759\u6001\u3001\u8fd4\u56de\u503c\u4e3a ",Object(i.b)("inlineCode",{parentName:"li"},"void")," \u4e14\u65b9\u6cd5\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f ",Object(i.b)("inlineCode",{parentName:"li"},"IApplicationBuilder")," \u7c7b\u578b\uff0c\u7b2c\u4e8c\u4e2a\u53c2\u6570\u662f ",Object(i.b)("inlineCode",{parentName:"li"},"IWebHostEnvironment")," \u7c7b\u578b\uff0c\u90a3\u4e48\u4ed6\u5c31\u662f\u4e00\u4e2a ",Object(i.b)("inlineCode",{parentName:"li"},"Configure")," \u65b9\u6cd5")),Object(i.b)("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"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{5,7,12,18,23}","{5,7,12,18,23}":!0}),"using Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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")),Object(i.b)("h3",{id:"323-appstartup-\u914d\u7f6e\u987a\u5e8f"},"3.2.3 ",Object(i.b)("inlineCode",{parentName:"h3"},"AppStartup")," \u914d\u7f6e\u987a\u5e8f"),Object(i.b)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",Object(i.b)("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 ",Object(i.b)("inlineCode",{parentName:"p"},"AppStartup")," \u6d3e\u751f\u7c7b\u4e2d\u8d34 ",Object(i.b)("inlineCode",{parentName:"p"},"[AppStartup(order)]")," \u7279\u6027\u5373\u53ef\u3002"),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"order")," \u6570\u503c\u8d8a\u5927\uff0c\u7ea6\u5728\u524d\u9762\u8c03\u7528\uff0c\u5982\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{5}","{5}":!0}),"using Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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")),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{5}","{5}":!0}),"using Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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")),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"FirstStartup")," \u4f1a\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"SecondStartup")," \u4e4b\u524d\u8c03\u7528\u3002"),Object(i.b)("h3",{id:"324-appstartup-\u65b9\u6cd5\u8c03\u7528\u987a\u5e8f"},"3.2.4 ",Object(i.b)("inlineCode",{parentName:"h3"},"AppStartup")," \u65b9\u6cd5\u8c03\u7528\u987a\u5e8f"),Object(i.b)("p",null,Object(i.b)("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"),Object(i.b)("h2",{id:"33-\u6846\u67b6\u9ed8\u8ba4-appstartup-\u5b9e\u73b0"},"3.3 \u6846\u67b6\u9ed8\u8ba4 ",Object(i.b)("inlineCode",{parentName:"h2"},"AppStartup")," \u5b9e\u73b0"),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u9ed8\u8ba4\u5728\u6bcf\u4e00\u4e2a\u9879\u76ee\u5c42\u4e2d\u90fd\u521b\u5efa\u4e86\u4e00\u4e2a ",Object(i.b)("inlineCode",{parentName:"p"},"AppStartup")," \u6d3e\u751f\u7c7b\uff0c\u65b9\u4fbf\u5927\u5bb6\u914d\u7f6e\u3002\u5982\uff1a"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"FurStartup.cs"),"\uff1a",Object(i.b)("inlineCode",{parentName:"li"},"Fur")," \u6846\u67b6\u6838\u5fc3\u542f\u52a8\u7c7b\uff08\u901a\u5e38\u65e0\u9700\u914d\u7f6e\uff09"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"FurApplicationStartup.cs"),"\uff1a\u4e1a\u52a1\u670d\u52a1\u542f\u52a8\u7c7b"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"FurCoreStartup.cs"),"\uff1a\u5e94\u7528\u6838\u5fc3\u529f\u80fd\u542f\u52a8\u7c7b"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"FurEntityFrameworkCoreStartup.cs"),"\uff1a\u6570\u636e\u5e93\u76f8\u5173\u542f\u52a8\u7c7b"),Object(i.b)("li",{parentName:"ul"},Object(i.b)("inlineCode",{parentName:"li"},"FurWebCoreStartup.cs"),"\uff1a",Object(i.b)("inlineCode",{parentName:"li"},"Web")," \u6838\u5fc3\u542f\u52a8\u914d\u7f6e\u7c7b")),Object(i.b)("h2",{id:"34-startup-\u914d\u7f6e\u6700\u4f73\u5b9e\u8df5"},"3.4 ",Object(i.b)("inlineCode",{parentName:"h2"},"Startup")," \u914d\u7f6e\u6700\u4f73\u5b9e\u8df5"),Object(i.b)("p",null,"\u5efa\u8bae ",Object(i.b)("inlineCode",{parentName:"p"},"Web")," \u542f\u52a8\u5c42\u7684 ",Object(i.b)("inlineCode",{parentName:"p"},"Startup.cs")," \u4fdd\u6301\u4e3a\u7a7a\u65b9\u6cd5\u4f53\uff0c\u5982\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'title="Fur.Web.Entry\\Startup.cs"',title:'"Fur.Web.Entry\\Startup.cs"'}),"using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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")),Object(i.b)("p",null,"\u5c06\u6240\u6709 ",Object(i.b)("inlineCode",{parentName:"p"},"Web \u5e94\u7528\u5c42")," \u914d\u7f6e\u8fc1\u79fb\u5230 ",Object(i.b)("inlineCode",{parentName:"p"},"FurWebCoreStartup.cs")," \u4e2d\uff0c\u5982\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:'title="Fur.Web.Core\\FurWebCoreStartup.cs"',title:'"Fur.Web.Core\\FurWebCoreStartup.cs"'}),"using Fur.UnifyResult;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace Fur.Web.Core\n{\n [AppStartup(800)]\n public sealed class FurWebCoreStartup : AppStartup\n {\n public void ConfigureServices(IServiceCollection services)\n {\n services.AddCorsAccessor();\n\n services.AddSpecificationDocuments();\n services.AddControllers()\n .AddDynamicApiControllers()\n .AddDataValidation()\n .AddFriendlyException()\n .AddUnifyResult();\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.UseSpecificationDocuments();\n\n app.UseEndpoints(endpoints =>\n {\n endpoints.MapControllers();\n });\n }\n }\n}\n")),Object(i.b)("p",null,"\u8fd9\u6837\uff0c\u540e\u7eed\u66f4\u6362 ",Object(i.b)("inlineCode",{parentName:"p"},"Web \u5e94\u7528\u5c42")," \u4e5f\u65e0\u9700\u91cd\u65b0\u914d\u7f6e ",Object(i.b)("inlineCode",{parentName:"p"},"Startup.cs")),Object(i.b)("h2",{id:"35-\u5173\u4e8e-appsettingsjson"},"3.5 \u5173\u4e8e ",Object(i.b)("inlineCode",{parentName:"h2"},"appsettings.json")),Object(i.b)("p",null,"\u5728\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c",Object(i.b)("inlineCode",{parentName:"p"},"ASP.NET Core")," \u914d\u7f6e\u653e\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"appsettings.json")," \u4e2d\u914d\u7f6e\uff0c\u4f46\u662f\u8fd9\u6837\u7684\u65b9\u5f0f\u548c ",Object(i.b)("inlineCode",{parentName:"p"},"Startup.cs")," \u914d\u7f6e\u4e00\u6837\u7684\u9053\u7406\uff0c\u4e00\u65e6\u6211\u4eec\u66f4\u6362\u4e86 ",Object(i.b)("inlineCode",{parentName:"p"},"Web \u5e94\u7528\u5c42"),"\uff0c\u90a3\u4e48 ",Object(i.b)("inlineCode",{parentName:"p"},"appsettings.json")," \u53c8\u8981\u91cd\u65b0\u914d\u7f6e\u4e00\u6b21\u3002"),Object(i.b)("p",null,"\u6240\u4ee5\uff0c",Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u63d0\u4f9b\u4e86\u66f4\u52a0\u7075\u6d3b\u7684\u65b9\u5f0f\u914d\u7f6e ",Object(i.b)("inlineCode",{parentName:"p"},"appsettings.json"),"\uff0c",Object(i.b)("strong",{parentName:"p"},"\u53ea\u9700\u8981\u5728\u4efb\u4f55\u9879\u76ee\u5c42\u6839\u76ee\u5f55\u4e0b\u521b\u5efa ",Object(i.b)("inlineCode",{parentName:"strong"},".json")," \u6587\u4ef6\u5373\u53ef")),Object(i.b)("p",null,Object(i.b)("strong",{parentName:"p"},Object(i.b)("inlineCode",{parentName:"strong"},"Fur")," \u6846\u67b6\u6700\u540e\u4f1a\u81ea\u52a8\u5408\u5e76\u6240\u6709\u5206\u6563\u7684\u914d\u7f6e\u6587\u4ef6\u3002")),Object(i.b)("p",null,"\u5982\u6211\u4eec\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u5c42\u521b\u5efa ",Object(i.b)("inlineCode",{parentName:"p"},"dbsettings.json")," \u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u5982\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-json",metastring:'title="Fur.EntityFramework.Core\\dbsettings.json"',title:'"Fur.EntityFramework.Core\\dbsettings.json"'}),'{\n "ConnectionStrings": {\n "DbConnectionString": "Server=localhost;Database=Fur;User=sa;Password=000000;MultipleActiveResultSets=True;",\n "Sqlite3ConnectionString": "Data Source=./Fur.db"\n }\n}\n')),Object(i.b)("p",null,Object(i.b)("strong",{parentName:"p"},"\u65e0\u9700\u5728 ",Object(i.b)("inlineCode",{parentName:"strong"},"appsettings.json")," \u4e2d\u914d\u7f6e"),"\uff0c\u4e0b\u9762\u662f ",Object(i.b)("inlineCode",{parentName:"p"},"appsettings.json")," \u9ed8\u8ba4\u4ee3\u7801:"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-json"}),'{\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')),Object(i.b)("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"),Object(i.b)("h2",{id:"36-\u795e\u5947\u7684-inject"},"3.6 \u795e\u5947\u7684 ",Object(i.b)("inlineCode",{parentName:"h2"},"Inject()")),Object(i.b)("p",null,Object(i.b)("inlineCode",{parentName:"p"},"Inject()")," \u65b9\u6cd5\u662f ",Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u63d0\u4f9b\u7684\u6700\u5c0f\u4fb5\u5165\u5f0f\u7684\u65b9\u6cd5\uff0c\u53ef\u4ee5\u8ba9\u4efb\u4f55 ",Object(i.b)("inlineCode",{parentName:"p"},"ASP.NET Core")," Web\u9879\u76ee\u77ac\u95f4\u652f\u6301\u6240\u6709 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u7279\u6027\u3002"),Object(i.b)("p",null,"\u6211\u4eec\u521b\u5efa\u4e86\u65b0\u7684 ",Object(i.b)("inlineCode",{parentName:"p"},"Web \u9879\u76ee"),"\uff0c\u53ea\u9700\u8981\u4e24\u4e2a\u6b65\u9aa4\u5373\u53ef\uff1a"),Object(i.b)("ul",null,Object(i.b)("li",{parentName:"ul"},"\u6dfb\u52a0 ",Object(i.b)("inlineCode",{parentName:"li"},"Fur.Web.Core")," \u9879\u76ee\u5f15\u7528"),Object(i.b)("li",{parentName:"ul"},"\u5728 ",Object(i.b)("inlineCode",{parentName:"li"},"Program.cs")," \u4e2d\u8c03\u7528\u5373\u53ef")),Object(i.b)("p",null,"\u5982\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs",metastring:"{18}","{18}":!0}),"using Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Hosting;\n\nnamespace Fur.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")),Object(i.b)("p",null,"\u975e\u5e38\u7b80\u5355\u5427\u3002\u6211\u4eec\u540e\u7eed\u521b\u5efa\u4efb\u4f55 ",Object(i.b)("inlineCode",{parentName:"p"},"MVC"),"\uff0c",Object(i.b)("inlineCode",{parentName:"p"},"RazorPages"),"\uff0c",Object(i.b)("inlineCode",{parentName:"p"},"Blazor")," \u9879\u76ee\u53ea\u9700\u8981\u6dfb\u52a0 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Web.Core")," \u5f15\u7528\u548c\u8c03\u7528 ",Object(i.b)("inlineCode",{parentName:"p"},"Inject()")," \u5373\u53ef\u3002"),Object(i.b)("h2",{id:"37-\u53cd\u9988\u4e0e\u5efa\u8bae"},"3.7 \u53cd\u9988\u4e0e\u5efa\u8bae"),Object(i.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e0e\u6211\u4eec\u4ea4\u6d41")),Object(i.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},"\u7ed9 Fur \u63d0 ",Object(i.b)("a",Object(a.a)({parentName:"p"},{href:"https://gitee.com/monksoul/Fur/issues/new?issue"}),"Issue"),"\u3002"))))}l.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/5ce0ebbd.5a25ca36.js b/handbook/build/5ce0ebbd.5a25ca36.js deleted file mode 100644 index b97a5b596f2..00000000000 --- a/handbook/build/5ce0ebbd.5a25ca36.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[35],{138:function(e,t,r){"use strict";r.d(t,"a",(function(){return s})),r.d(t,"b",(function(){return m}));var n=r(0),o=r.n(n);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 c(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 u=o.a.createContext({}),l=function(e){var t=o.a.useContext(u),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},s=function(e){var t=l(e.components);return o.a.createElement(u.Provider,{value:t},e.children)},f={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},d=o.a.forwardRef((function(e,t){var r=e.components,n=e.mdxType,a=e.originalType,c=e.parentName,u=p(e,["components","mdxType","originalType","parentName"]),s=l(r),d=n,m=s["".concat(c,".").concat(d)]||s[d]||f[d]||a;return r?o.a.createElement(m,i(i({ref:t},u),{},{components:r})):o.a.createElement(m,i({ref:t},u))}));function m(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=r.length,c=new Array(a);c[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:n,c[1]=i;for(var u=2;u=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var s=o.a.createContext({}),d=function(e){var n=o.a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},u=function(e){var n=d(e.components);return o.a.createElement(s.Provider,{value:n},e.children)},b={inlineCode:"code",wrapper:function(e){var n=e.children;return o.a.createElement(o.a.Fragment,{},n)}},m=o.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,r=e.originalType,c=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),u=d(t),m=a,p=u["".concat(c,".").concat(m)]||u[m]||b[m]||r;return t?o.a.createElement(p,i(i({ref:n},s),{},{components:t})):o.a.createElement(p,i({ref:n},s))}));function p(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var r=t.length,c=new Array(r);c[0]=m;var i={};for(var l in n)hasOwnProperty.call(n,l)&&(i[l]=n[l]);i.originalType=e,i.mdxType="string"==typeof e?e:a,c[1]=i;for(var s=2;sDbConnectionInterceptor",id:"92421-dbconnectioninterceptor",children:[]},{value:"9.24.2.2 DbCommandInterceptor",id:"92422-dbcommandinterceptor",children:[]},{value:"9.24.2.3 SaveChangesInterceptor",id:"92423-savechangesinterceptor",children:[]}]},{value:"9.24.3 \u6ce8\u518c\u81ea\u5b9a\u4e49\u8fc7\u6ee4\u5668",id:"9243-\u6ce8\u518c\u81ea\u5b9a\u4e49\u8fc7\u6ee4\u5668",children:[]},{value:"9.24.4 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9244-\u53cd\u9988\u4e0e\u5efa\u8bae",children:[]}],s={rightToc:l};function d(e){var n=e.components,t=Object(o.a)(e,["components"]);return Object(r.b)("wrapper",Object(a.a)({},s,t,{components:n,mdxType:"MDXLayout"}),Object(r.b)("h2",{id:"9241-\u6570\u636e\u5e93\u62e6\u622a\u5668"},"9.24.1 \u6570\u636e\u5e93\u62e6\u622a\u5668"),Object(r.b)("p",null,Object(r.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u63d0\u4f9b\u4e09\u79cd\u6570\u636e\u5e93\u64cd\u4f5c\u62e6\u622a\u5668\uff0c\u53ef\u4ee5\u901a\u8fc7\u62e6\u622a\u5668\u52a8\u6001\u4fee\u6539\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u52a8\u6001\u4fee\u6539sql\uff0c\u52a8\u6001\u66f4\u6539\u53c2\u6570\u7b49\u64cd\u4f5c\u3002"),Object(r.b)("p",null,"\u76ee\u524d\u652f\u6301\u8fd9\u4e09\u79cd\u62e6\u622a\u5668\uff1a"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"DbConnectionInterceptor"),"\uff1a\u6570\u636e\u5e93\u8fde\u63a5\u62e6\u622a\u5668"),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"DbCommandInterceptor"),"\uff1a\u6570\u636e\u5e93\u6267\u884c ",Object(r.b)("inlineCode",{parentName:"li"},"Sql")," \u62e6\u622a\u5668"),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"SaveChangesInterceptor"),"\uff1a\u63d0\u4ea4\u5230\u6570\u636e\u5e93\u62e6\u622a\u5668")),Object(r.b)("h2",{id:"9242-\u652f\u6301\u62e6\u622a\u7c7b\u578b"},"9.24.2 \u652f\u6301\u62e6\u622a\u7c7b\u578b"),Object(r.b)("h3",{id:"92421-dbconnectioninterceptor"},"9.24.2.1 ",Object(r.b)("inlineCode",{parentName:"h3"},"DbConnectionInterceptor")),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"using Microsoft.EntityFrameworkCore.Diagnostics;\nusing System.Data.Common;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Fur.DatabaseAccessor.Interceptors\n{\n public class SqlConnectionInterceptor : DbConnectionInterceptor\n {\n // \u6570\u636e\u5e93\u8fde\u63a5\u4e4b\u524d\n public override InterceptionResult ConnectionOpening(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)\n {\n return base.ConnectionOpening(connection, eventData, result);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask ConnectionOpeningAsync(DbConnection connection, ConnectionEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n return base.ConnectionOpeningAsync(connection, eventData, result, cancellationToken);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u6210\u529f\n public override void ConnectionOpened(DbConnection connection, ConnectionEndEventData eventData)\n {\n base.ConnectionOpened(connection, eventData);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u6210\u529f\uff08\u5f02\u6b65\uff09\n public override Task ConnectionOpenedAsync(DbConnection connection, ConnectionEndEventData eventData, CancellationToken cancellationToken = default)\n {\n return base.ConnectionOpenedAsync(connection, eventData, cancellationToken);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5173\u95ed\u4e4b\u524d\n public override InterceptionResult ConnectionClosing(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)\n {\n return base.ConnectionClosing(connection, eventData, result);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5173\u95ed\u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask ConnectionClosingAsync(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)\n {\n return base.ConnectionClosingAsync(connection, eventData, result);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5173\u95ed\u6210\u529f\n public override void ConnectionClosed(DbConnection connection, ConnectionEndEventData eventData)\n {\n base.ConnectionClosed(connection, eventData);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5173\u95ed\u6210\u529f\uff08\u5f02\u6b65\uff09\n public override Task ConnectionClosedAsync(DbConnection connection, ConnectionEndEventData eventData)\n {\n return base.ConnectionClosedAsync(connection, eventData);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5931\u8d25\n public override void ConnectionFailed(DbConnection connection, ConnectionErrorEventData eventData)\n {\n base.ConnectionFailed(connection, eventData);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5931\u8d25\uff08\u5f02\u6b65\uff09\n public override Task ConnectionFailedAsync(DbConnection connection, ConnectionErrorEventData eventData, CancellationToken cancellationToken = default)\n {\n return base.ConnectionFailedAsync(connection, eventData, cancellationToken);\n }\n }\n}\n")),Object(r.b)("h3",{id:"92422-dbcommandinterceptor"},"9.24.2.2 ",Object(r.b)("inlineCode",{parentName:"h3"},"DbCommandInterceptor")),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"using Microsoft.EntityFrameworkCore.Diagnostics;\nusing System.Data.Common;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Fur.DatabaseAccessor\n{\n internal sealed class SqlCommandProfilerInterceptor : DbCommandInterceptor\n {\n // \u521b\u5efa\u547d\u4ee4\u5bf9\u8c61\u4e4b\u524d\n public override InterceptionResult CommandCreating(CommandCorrelatedEventData eventData, InterceptionResult result)\n {\n return base.CommandCreating(eventData, result);\n }\n\n // \u521b\u5efa\u547d\u4ee4\u5bf9\u8c61\u4e4b\u540e\n public override DbCommand CommandCreated(CommandEndEventData eventData, DbCommand result)\n {\n return base.CommandCreated(eventData, result);\n }\n\n // \u521b\u5efa\u547d\u4ee4\u5bf9\u8c61\u5931\u8d25\n public override void CommandFailed(DbCommand command, CommandErrorEventData eventData)\n {\n base.CommandFailed(command, eventData);\n }\n\n // \u521b\u5efa\u547d\u4ee4\u5bf9\u8c61\u5931\u8d25\uff08\u5f02\u6b65\uff09\n public override Task CommandFailedAsync(DbCommand command, CommandErrorEventData eventData, CancellationToken cancellationToken = default)\n {\n return base.CommandFailedAsync(command, eventData, cancellationToken);\n }\n\n // \u8bfb\u53d6\u6570\u636e\u4e4b\u524d\n public override InterceptionResult ReaderExecuting(DbCommand command, CommandEventData eventData, InterceptionResult result)\n {\n return base.ReaderExecuting(command, eventData, result);\n }\n\n // \u8bfb\u53d6\u6570\u636e\u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask> ReaderExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n return base.ReaderExecutingAsync(command, eventData, result, cancellationToken);\n }\n\n // \u8bfb\u53d6\u6570\u636e\u4e4b\u540e\n public override DbDataReader ReaderExecuted(DbCommand command, CommandExecutedEventData eventData, DbDataReader result)\n {\n return base.ReaderExecuted(command, eventData, result);\n }\n\n // \u8bfb\u53d6\u6570\u636e\u4e4b\u540e\uff08\u5f02\u6b65\uff09\n public override ValueTask ReaderExecutedAsync(DbCommand command, CommandExecutedEventData eventData, DbDataReader result, CancellationToken cancellationToken = default)\n {\n return base.ReaderExecutedAsync(command, eventData, result, cancellationToken);\n }\n\n // DataReader \u5bf9\u8c61\u91ca\u653e\u4e4b\u524d\n public override InterceptionResult DataReaderDisposing(DbCommand command, DataReaderDisposingEventData eventData, InterceptionResult result)\n {\n return base.DataReaderDisposing(command, eventData, result);\n }\n\n // \u65e0\u67e5\u8be2\u6267\u884c sql \u4e4b\u524d\n public override InterceptionResult NonQueryExecuting(DbCommand command, CommandEventData eventData, InterceptionResult result)\n {\n return base.NonQueryExecuting(command, eventData, result);\n }\n\n // \u65e0\u67e5\u8be2\u6267\u884c sql \u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask> NonQueryExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n return base.NonQueryExecutingAsync(command, eventData, result, cancellationToken);\n }\n\n // \u65e0\u67e5\u8be2\u6267\u884c sql \u4e4b\u540e\n public override int NonQueryExecuted(DbCommand command, CommandExecutedEventData eventData, int result)\n {\n return base.NonQueryExecuted(command, eventData, result);\n }\n\n // \u65e0\u67e5\u8be2\u6267\u884c sql \u4e4b\u540e\uff08\u5f02\u6b65\uff09\n public override ValueTask NonQueryExecutedAsync(DbCommand command, CommandExecutedEventData eventData, int result, CancellationToken cancellationToken = default)\n {\n return base.NonQueryExecutedAsync(command, eventData, result, cancellationToken);\n }\n\n // \u6267\u884c sql \u8fd4\u56de\u5355\u884c\u5355\u5217\u4e4b\u524d\n public override InterceptionResult ScalarExecuting(DbCommand command, CommandEventData eventData, InterceptionResult result)\n {\n return base.ScalarExecuting(command, eventData, result);\n }\n\n // \u6267\u884c sql \u8fd4\u56de\u5355\u884c\u5355\u5217\u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask> ScalarExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n return base.ScalarExecutingAsync(command, eventData, result, cancellationToken);\n }\n\n // \u6267\u884c sql \u8fd4\u56de\u5355\u884c\u5355\u5217\u4e4b\u540e\n public override object ScalarExecuted(DbCommand command, CommandExecutedEventData eventData, object result)\n {\n return base.ScalarExecuted(command, eventData, result);\n }\n\n // \u6267\u884c sql \u8fd4\u56de\u5355\u884c\u5355\u5217\u4e4b\u540e\uff08\u5f02\u6b65\uff09\n public override ValueTask ScalarExecutedAsync(DbCommand command, CommandExecutedEventData eventData, object result, CancellationToken cancellationToken = default)\n {\n return base.ScalarExecutedAsync(command, eventData, result, cancellationToken);\n }\n }\n}\n")),Object(r.b)("h3",{id:"92423-savechangesinterceptor"},"9.24.2.3 ",Object(r.b)("inlineCode",{parentName:"h3"},"SaveChangesInterceptor")),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"using Microsoft.EntityFrameworkCore.Diagnostics;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Fur.DatabaseAccessor\n{\n public class DbContextSaveChangesInterceptor : SaveChangesInterceptor\n {\n // \u63d0\u4ea4\u5230\u6570\u636e\u5e93\u4e4b\u524d\n public override InterceptionResult SavingChanges(DbContextEventData eventData, InterceptionResult result)\n {\n return base.SavingChanges(eventData, result);\n }\n\n // \u63d0\u4ea4\u5230\u6570\u636e\u5e93\u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask> SavingChangesAsync(DbContextEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n return base.SavingChangesAsync(eventData, result, cancellationToken);\n }\n\n // \u63d0\u4ea4\u5230\u6570\u636e\u5e93\u4e4b\u540e\n public override int SavedChanges(SaveChangesCompletedEventData eventData, int result)\n {\n return base.SavedChanges(eventData, result);\n }\n\n // \u63d0\u4ea4\u5230\u6570\u636e\u5e93\u4e4b\u540e\uff08\u5f02\u6b65\uff09\n public override ValueTask SavedChangesAsync(SaveChangesCompletedEventData eventData, int result, CancellationToken cancellationToken = default)\n {\n return base.SavedChangesAsync(eventData, result, cancellationToken);\n }\n\n // \u63d0\u4ea4\u6570\u636e\u5e93\u5931\u8d25\n public override void SaveChangesFailed(DbContextErrorEventData eventData)\n {\n base.SaveChangesFailed(eventData);\n }\n\n // \u63d0\u4ea4\u6570\u636e\u5e93\u5931\u8d25\uff08\u5f02\u6b65\uff09\n public override Task SaveChangesFailedAsync(DbContextErrorEventData eventData, CancellationToken cancellationToken = default)\n {\n return base.SaveChangesFailedAsync(eventData, cancellationToken);\n }\n }\n}\n")),Object(r.b)("h2",{id:"9243-\u6ce8\u518c\u81ea\u5b9a\u4e49\u8fc7\u6ee4\u5668"},"9.24.3 \u6ce8\u518c\u81ea\u5b9a\u4e49\u8fc7\u6ee4\u5668"),Object(r.b)("p",null,"\u5b9a\u4e49\u597d\u8fc7\u6ee4\u5668\u4e4b\u540e\uff0c\u6211\u4eec\u9700\u8981\u5728\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u6ce8\u518c\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"services.AddSqlitePool(interceptors: new IInterceptor[] {\n new SqlConnectionProfilerInterceptor(),\n new DbContextSaveChangesInterceptor(),\n new SqlCommandProfilerInterceptor()\n});\n")),Object(r.b)("h2",{id:"9244-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.24.4 \u53cd\u9988\u4e0e\u5efa\u8bae"),Object(r.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e0e\u6211\u4eec\u4ea4\u6d41")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u7ed9 Fur \u63d0 ",Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://gitee.com/monksoul/Fur/issues/new?issue"}),"Issue"),"\u3002"))))}d.isMDXComponent=!0}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[42],{138:function(e,n,t){"use strict";t.d(n,"a",(function(){return u})),t.d(n,"b",(function(){return p}));var a=t(0),o=t.n(a);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 c(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||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var s=o.a.createContext({}),d=function(e){var n=o.a.useContext(s),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},u=function(e){var n=d(e.components);return o.a.createElement(s.Provider,{value:n},e.children)},b={inlineCode:"code",wrapper:function(e){var n=e.children;return o.a.createElement(o.a.Fragment,{},n)}},m=o.a.forwardRef((function(e,n){var t=e.components,a=e.mdxType,r=e.originalType,c=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),u=d(t),m=a,p=u["".concat(c,".").concat(m)]||u[m]||b[m]||r;return t?o.a.createElement(p,i(i({ref:n},s),{},{components:t})):o.a.createElement(p,i({ref:n},s))}));function p(e,n){var t=arguments,a=n&&n.mdxType;if("string"==typeof e||a){var r=t.length,c=new Array(r);c[0]=m;var i={};for(var l in n)hasOwnProperty.call(n,l)&&(i[l]=n[l]);i.originalType=e,i.mdxType="string"==typeof e?e:a,c[1]=i;for(var s=2;sDbConnectionInterceptor",id:"92421-dbconnectioninterceptor",children:[]},{value:"9.24.2.2 DbCommandInterceptor",id:"92422-dbcommandinterceptor",children:[]},{value:"9.24.2.3 SaveChangesInterceptor",id:"92423-savechangesinterceptor",children:[]}]},{value:"9.24.3 \u6ce8\u518c\u81ea\u5b9a\u4e49\u8fc7\u6ee4\u5668",id:"9243-\u6ce8\u518c\u81ea\u5b9a\u4e49\u8fc7\u6ee4\u5668",children:[]},{value:"9.24.4 \u53cd\u9988\u4e0e\u5efa\u8bae",id:"9244-\u53cd\u9988\u4e0e\u5efa\u8bae",children:[]}],s={rightToc:l};function d(e){var n=e.components,t=Object(o.a)(e,["components"]);return Object(r.b)("wrapper",Object(a.a)({},s,t,{components:n,mdxType:"MDXLayout"}),Object(r.b)("h2",{id:"9241-\u6570\u636e\u5e93\u62e6\u622a\u5668"},"9.24.1 \u6570\u636e\u5e93\u62e6\u622a\u5668"),Object(r.b)("p",null,Object(r.b)("inlineCode",{parentName:"p"},"Fur")," \u6846\u67b6\u63d0\u4f9b\u4e09\u79cd\u6570\u636e\u5e93\u64cd\u4f5c\u62e6\u622a\u5668\uff0c\u53ef\u4ee5\u901a\u8fc7\u62e6\u622a\u5668\u52a8\u6001\u4fee\u8be5\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u52a8\u6001\u4fee\u6539sql\uff0c\u52a8\u6001\u66f4\u6539\u53c2\u6570\u7b49\u64cd\u4f5c\u3002"),Object(r.b)("p",null,"\u76ee\u524d\u652f\u6301\u8fd9\u4e09\u79cd\u62e6\u622a\u5668\uff1a"),Object(r.b)("ul",null,Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"DbConnectionInterceptor"),"\uff1a\u6570\u636e\u5e93\u8fde\u63a5\u62e6\u622a\u5668"),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"DbCommandInterceptor"),"\uff1a\u6570\u636e\u5e93\u6267\u884c ",Object(r.b)("inlineCode",{parentName:"li"},"Sql")," \u62e6\u622a\u5668"),Object(r.b)("li",{parentName:"ul"},Object(r.b)("inlineCode",{parentName:"li"},"SaveChangesInterceptor"),"\uff1a\u63d0\u4ea4\u5230\u6570\u636e\u5e93\u62e6\u622a\u5668")),Object(r.b)("h2",{id:"9242-\u652f\u6301\u62e6\u622a\u7c7b\u578b"},"9.24.2 \u652f\u6301\u62e6\u622a\u7c7b\u578b"),Object(r.b)("h3",{id:"92421-dbconnectioninterceptor"},"9.24.2.1 ",Object(r.b)("inlineCode",{parentName:"h3"},"DbConnectionInterceptor")),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"using Microsoft.EntityFrameworkCore.Diagnostics;\nusing System.Data.Common;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Fur.DatabaseAccessor.Interceptors\n{\n public class SqlConnectionInterceptor : DbConnectionInterceptor\n {\n // \u6570\u636e\u5e93\u8fde\u63a5\u4e4b\u524d\n public override InterceptionResult ConnectionOpening(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)\n {\n return base.ConnectionOpening(connection, eventData, result);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask ConnectionOpeningAsync(DbConnection connection, ConnectionEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n return base.ConnectionOpeningAsync(connection, eventData, result, cancellationToken);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u6210\u529f\n public override void ConnectionOpened(DbConnection connection, ConnectionEndEventData eventData)\n {\n base.ConnectionOpened(connection, eventData);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u6210\u529f\uff08\u5f02\u6b65\uff09\n public override Task ConnectionOpenedAsync(DbConnection connection, ConnectionEndEventData eventData, CancellationToken cancellationToken = default)\n {\n return base.ConnectionOpenedAsync(connection, eventData, cancellationToken);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5173\u95ed\u4e4b\u524d\n public override InterceptionResult ConnectionClosing(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)\n {\n return base.ConnectionClosing(connection, eventData, result);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5173\u95ed\u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask ConnectionClosingAsync(DbConnection connection, ConnectionEventData eventData, InterceptionResult result)\n {\n return base.ConnectionClosingAsync(connection, eventData, result);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5173\u95ed\u6210\u529f\n public override void ConnectionClosed(DbConnection connection, ConnectionEndEventData eventData)\n {\n base.ConnectionClosed(connection, eventData);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5173\u95ed\u6210\u529f\uff08\u5f02\u6b65\uff09\n public override Task ConnectionClosedAsync(DbConnection connection, ConnectionEndEventData eventData)\n {\n return base.ConnectionClosedAsync(connection, eventData);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5931\u8d25\n public override void ConnectionFailed(DbConnection connection, ConnectionErrorEventData eventData)\n {\n base.ConnectionFailed(connection, eventData);\n }\n\n // \u6570\u636e\u5e93\u8fde\u63a5\u5931\u8d25\uff08\u5f02\u6b65\uff09\n public override Task ConnectionFailedAsync(DbConnection connection, ConnectionErrorEventData eventData, CancellationToken cancellationToken = default)\n {\n return base.ConnectionFailedAsync(connection, eventData, cancellationToken);\n }\n }\n}\n")),Object(r.b)("h3",{id:"92422-dbcommandinterceptor"},"9.24.2.2 ",Object(r.b)("inlineCode",{parentName:"h3"},"DbCommandInterceptor")),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"using Microsoft.EntityFrameworkCore.Diagnostics;\nusing System.Data.Common;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Fur.DatabaseAccessor\n{\n internal sealed class SqlCommandProfilerInterceptor : DbCommandInterceptor\n {\n // \u521b\u5efa\u547d\u4ee4\u5bf9\u8c61\u4e4b\u524d\n public override InterceptionResult CommandCreating(CommandCorrelatedEventData eventData, InterceptionResult result)\n {\n return base.CommandCreating(eventData, result);\n }\n\n // \u521b\u5efa\u547d\u4ee4\u5bf9\u8c61\u4e4b\u540e\n public override DbCommand CommandCreated(CommandEndEventData eventData, DbCommand result)\n {\n return base.CommandCreated(eventData, result);\n }\n\n // \u521b\u5efa\u547d\u4ee4\u5bf9\u8c61\u5931\u8d25\n public override void CommandFailed(DbCommand command, CommandErrorEventData eventData)\n {\n base.CommandFailed(command, eventData);\n }\n\n // \u521b\u5efa\u547d\u4ee4\u5bf9\u8c61\u5931\u8d25\uff08\u5f02\u6b65\uff09\n public override Task CommandFailedAsync(DbCommand command, CommandErrorEventData eventData, CancellationToken cancellationToken = default)\n {\n return base.CommandFailedAsync(command, eventData, cancellationToken);\n }\n\n // \u8bfb\u53d6\u6570\u636e\u4e4b\u524d\n public override InterceptionResult ReaderExecuting(DbCommand command, CommandEventData eventData, InterceptionResult result)\n {\n return base.ReaderExecuting(command, eventData, result);\n }\n\n // \u8bfb\u53d6\u6570\u636e\u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask> ReaderExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n return base.ReaderExecutingAsync(command, eventData, result, cancellationToken);\n }\n\n // \u8bfb\u53d6\u6570\u636e\u4e4b\u540e\n public override DbDataReader ReaderExecuted(DbCommand command, CommandExecutedEventData eventData, DbDataReader result)\n {\n return base.ReaderExecuted(command, eventData, result);\n }\n\n // \u8bfb\u53d6\u6570\u636e\u4e4b\u540e\uff08\u5f02\u6b65\uff09\n public override ValueTask ReaderExecutedAsync(DbCommand command, CommandExecutedEventData eventData, DbDataReader result, CancellationToken cancellationToken = default)\n {\n return base.ReaderExecutedAsync(command, eventData, result, cancellationToken);\n }\n\n // DataReader \u5bf9\u8c61\u91ca\u653e\u4e4b\u524d\n public override InterceptionResult DataReaderDisposing(DbCommand command, DataReaderDisposingEventData eventData, InterceptionResult result)\n {\n return base.DataReaderDisposing(command, eventData, result);\n }\n\n // \u65e0\u67e5\u8be2\u6267\u884c sql \u4e4b\u524d\n public override InterceptionResult NonQueryExecuting(DbCommand command, CommandEventData eventData, InterceptionResult result)\n {\n return base.NonQueryExecuting(command, eventData, result);\n }\n\n // \u65e0\u67e5\u8be2\u6267\u884c sql \u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask> NonQueryExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n return base.NonQueryExecutingAsync(command, eventData, result, cancellationToken);\n }\n\n // \u65e0\u67e5\u8be2\u6267\u884c sql \u4e4b\u540e\n public override int NonQueryExecuted(DbCommand command, CommandExecutedEventData eventData, int result)\n {\n return base.NonQueryExecuted(command, eventData, result);\n }\n\n // \u65e0\u67e5\u8be2\u6267\u884c sql \u4e4b\u540e\uff08\u5f02\u6b65\uff09\n public override ValueTask NonQueryExecutedAsync(DbCommand command, CommandExecutedEventData eventData, int result, CancellationToken cancellationToken = default)\n {\n return base.NonQueryExecutedAsync(command, eventData, result, cancellationToken);\n }\n\n // \u6267\u884c sql \u8fd4\u56de\u5355\u884c\u5355\u5217\u4e4b\u524d\n public override InterceptionResult ScalarExecuting(DbCommand command, CommandEventData eventData, InterceptionResult result)\n {\n return base.ScalarExecuting(command, eventData, result);\n }\n\n // \u6267\u884c sql \u8fd4\u56de\u5355\u884c\u5355\u5217\u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask> ScalarExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n return base.ScalarExecutingAsync(command, eventData, result, cancellationToken);\n }\n\n // \u6267\u884c sql \u8fd4\u56de\u5355\u884c\u5355\u5217\u4e4b\u540e\n public override object ScalarExecuted(DbCommand command, CommandExecutedEventData eventData, object result)\n {\n return base.ScalarExecuted(command, eventData, result);\n }\n\n // \u6267\u884c sql \u8fd4\u56de\u5355\u884c\u5355\u5217\u4e4b\u540e\uff08\u5f02\u6b65\uff09\n public override ValueTask ScalarExecutedAsync(DbCommand command, CommandExecutedEventData eventData, object result, CancellationToken cancellationToken = default)\n {\n return base.ScalarExecutedAsync(command, eventData, result, cancellationToken);\n }\n }\n}\n")),Object(r.b)("h3",{id:"92423-savechangesinterceptor"},"9.24.2.3 ",Object(r.b)("inlineCode",{parentName:"h3"},"SaveChangesInterceptor")),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"using Microsoft.EntityFrameworkCore.Diagnostics;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Fur.DatabaseAccessor\n{\n public class DbContextSaveChangesInterceptor : SaveChangesInterceptor\n {\n // \u63d0\u4ea4\u5230\u6570\u636e\u5e93\u4e4b\u524d\n public override InterceptionResult SavingChanges(DbContextEventData eventData, InterceptionResult result)\n {\n return base.SavingChanges(eventData, result);\n }\n\n // \u63d0\u4ea4\u5230\u6570\u636e\u5e93\u4e4b\u524d\uff08\u5f02\u6b65\uff09\n public override ValueTask> SavingChangesAsync(DbContextEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default)\n {\n return base.SavingChangesAsync(eventData, result, cancellationToken);\n }\n\n // \u63d0\u4ea4\u5230\u6570\u636e\u5e93\u4e4b\u540e\n public override int SavedChanges(SaveChangesCompletedEventData eventData, int result)\n {\n return base.SavedChanges(eventData, result);\n }\n\n // \u63d0\u4ea4\u5230\u6570\u636e\u5e93\u4e4b\u540e\uff08\u5f02\u6b65\uff09\n public override ValueTask SavedChangesAsync(SaveChangesCompletedEventData eventData, int result, CancellationToken cancellationToken = default)\n {\n return base.SavedChangesAsync(eventData, result, cancellationToken);\n }\n\n // \u63d0\u4ea4\u6570\u636e\u5e93\u5931\u8d25\n public override void SaveChangesFailed(DbContextErrorEventData eventData)\n {\n base.SaveChangesFailed(eventData);\n }\n\n // \u63d0\u4ea4\u6570\u636e\u5e93\u5931\u8d25\uff08\u5f02\u6b65\uff09\n public override Task SaveChangesFailedAsync(DbContextErrorEventData eventData, CancellationToken cancellationToken = default)\n {\n return base.SaveChangesFailedAsync(eventData, cancellationToken);\n }\n }\n}\n")),Object(r.b)("h2",{id:"9243-\u6ce8\u518c\u81ea\u5b9a\u4e49\u8fc7\u6ee4\u5668"},"9.24.3 \u6ce8\u518c\u81ea\u5b9a\u4e49\u8fc7\u6ee4\u5668"),Object(r.b)("p",null,"\u5b9a\u4e49\u597d\u8fc7\u6ee4\u5668\u4e4b\u540e\uff0c\u6211\u4eec\u9700\u8981\u5728\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\u4e2d\u6ce8\u518c\uff1a"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-cs"}),"services.AddSqlitePool(interceptors: new IInterceptor[] {\n new SqlConnectionProfilerInterceptor(),\n new DbContextSaveChangesInterceptor(),\n new SqlCommandProfilerInterceptor()\n});\n")),Object(r.b)("h2",{id:"9244-\u53cd\u9988\u4e0e\u5efa\u8bae"},"9.24.4 \u53cd\u9988\u4e0e\u5efa\u8bae"),Object(r.b)("div",{className:"admonition admonition-note alert alert--secondary"},Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-heading"}),Object(r.b)("h5",{parentName:"div"},Object(r.b)("span",Object(a.a)({parentName:"h5"},{className:"admonition-icon"}),Object(r.b)("svg",Object(a.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(r.b)("path",Object(a.a)({parentName:"svg"},{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"})))),"\u4e0e\u6211\u4eec\u4ea4\u6d41")),Object(r.b)("div",Object(a.a)({parentName:"div"},{className:"admonition-content"}),Object(r.b)("p",{parentName:"div"},"\u7ed9 Fur \u63d0 ",Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://gitee.com/monksoul/Fur/issues/new?issue"}),"Issue"),"\u3002"))))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/handbook/build/blog/index.html b/handbook/build/blog/index.html index d2d96a8aa64..364d19885e1 100644 --- a/handbook/build/blog/index.html +++ b/handbook/build/blog/index.html @@ -6,7 +6,7 @@ Blog | Fur - + @@ -25,7 +25,7 @@

    Fur 介绍

    dotnet中国

    dotnet中国

    为中国 .NET 开发者提供优质的资讯和技术分享。

    star fork GitHub stars GitHub forks GitHub license

    Fur.NET 5 平台下极易入门、极速开发的 Web 应用框架。

    🍕 名字的由来

    故事是这样子的:

    起初,想开发一个极易入门、极易维护的框架,开发理念为:一切从简,只为了更懒

    所以自然而然想到了:Lazier,也就是 更懒 的意思。但是 更懒更烂 读音相近且中文名没有特色,对此换名问题我苦恼了好几天。

    刚好有一次我在博客园中帮一个博友解答问题,解决后博友赞扬我对 .NET Core 颇有了解,我就顺嘴回答了一句:“略懂皮毛”

    就这时,脑瓜子灵机一动,干脆起名为:“皮毛”?英文单词 Fur [fɜː(r)]”,单词又短而且中文读音既俗气又顺口。😄😎

    所以,Fur 就诞生了。

    之后就有了 “小僧不才,略懂皮毛(Fur)。” 广告语 和 chinadot.net 域名。

    🍔 关于 LOGO

    Fur LOGO 设计由 F U R 三个单词组成:

    我相信很多人看到 Fur 的 LOGO 时都会问:“为什么选择奶牛?”,因为 那些年吹过的牛逼都实现了 🐮

    之所以选择 奶牛 是因为 具有脚踏实地,任劳任怨的做事风格,同时 奶牛 意味着丰富的营养价值,正如 Fur 所能带给你的。

    🍟 文档地址

    https://chinadot.net

    - + diff --git a/handbook/build/blog/tags/fur/index.html b/handbook/build/blog/tags/fur/index.html index c9666708f55..da71ddab47e 100644 --- a/handbook/build/blog/tags/fur/index.html +++ b/handbook/build/blog/tags/fur/index.html @@ -6,7 +6,7 @@ Posts tagged "fur" | Fur - + @@ -25,7 +25,7 @@

    1 post tagged with "fur"

    View All Tags

    Fur 介绍

    dotnet中国

    dotnet中国

    为中国 .NET 开发者提供优质的资讯和技术分享。

    star fork GitHub stars GitHub forks GitHub license

    Fur.NET 5 平台下极易入门、极速开发的 Web 应用框架。

    🍕 名字的由来

    故事是这样子的:

    起初,想开发一个极易入门、极易维护的框架,开发理念为:一切从简,只为了更懒

    所以自然而然想到了:Lazier,也就是 更懒 的意思。但是 更懒更烂 读音相近且中文名没有特色,对此换名问题我苦恼了好几天。

    刚好有一次我在博客园中帮一个博友解答问题,解决后博友赞扬我对 .NET Core 颇有了解,我就顺嘴回答了一句:“略懂皮毛”

    就这时,脑瓜子灵机一动,干脆起名为:“皮毛”?英文单词 Fur [fɜː(r)]”,单词又短而且中文读音既俗气又顺口。😄😎

    所以,Fur 就诞生了。

    之后就有了 “小僧不才,略懂皮毛(Fur)。” 广告语 和 chinadot.net 域名。

    🍔 关于 LOGO

    Fur LOGO 设计由 F U R 三个单词组成:

    我相信很多人看到 Fur 的 LOGO 时都会问:“为什么选择奶牛?”,因为 那些年吹过的牛逼都实现了 🐮

    之所以选择 奶牛 是因为 具有脚踏实地,任劳任怨的做事风格,同时 奶牛 意味着丰富的营养价值,正如 Fur 所能带给你的。

    🍟 文档地址

    https://chinadot.net

    - + diff --git a/handbook/build/blog/tags/furos/index.html b/handbook/build/blog/tags/furos/index.html index 7508cec14ea..9271e243aa2 100644 --- a/handbook/build/blog/tags/furos/index.html +++ b/handbook/build/blog/tags/furos/index.html @@ -6,7 +6,7 @@ Posts tagged "furos" | Fur - + @@ -25,7 +25,7 @@

    1 post tagged with "furos"

    View All Tags

    Fur 介绍

    dotnet中国

    dotnet中国

    为中国 .NET 开发者提供优质的资讯和技术分享。

    star fork GitHub stars GitHub forks GitHub license

    Fur.NET 5 平台下极易入门、极速开发的 Web 应用框架。

    🍕 名字的由来

    故事是这样子的:

    起初,想开发一个极易入门、极易维护的框架,开发理念为:一切从简,只为了更懒

    所以自然而然想到了:Lazier,也就是 更懒 的意思。但是 更懒更烂 读音相近且中文名没有特色,对此换名问题我苦恼了好几天。

    刚好有一次我在博客园中帮一个博友解答问题,解决后博友赞扬我对 .NET Core 颇有了解,我就顺嘴回答了一句:“略懂皮毛”

    就这时,脑瓜子灵机一动,干脆起名为:“皮毛”?英文单词 Fur [fɜː(r)]”,单词又短而且中文读音既俗气又顺口。😄😎

    所以,Fur 就诞生了。

    之后就有了 “小僧不才,略懂皮毛(Fur)。” 广告语 和 chinadot.net 域名。

    🍔 关于 LOGO

    Fur LOGO 设计由 F U R 三个单词组成:

    我相信很多人看到 Fur 的 LOGO 时都会问:“为什么选择奶牛?”,因为 那些年吹过的牛逼都实现了 🐮

    之所以选择 奶牛 是因为 具有脚踏实地,任劳任怨的做事风格,同时 奶牛 意味着丰富的营养价值,正如 Fur 所能带给你的。

    🍟 文档地址

    https://chinadot.net

    - + diff --git a/handbook/build/blog/tags/index.html b/handbook/build/blog/tags/index.html index e9b9adf9f87..260585fd2bb 100644 --- a/handbook/build/blog/tags/index.html +++ b/handbook/build/blog/tags/index.html @@ -6,7 +6,7 @@ Tags | Fur - + @@ -23,7 +23,7 @@ - + diff --git a/handbook/build/blog/tags/net-5/index.html b/handbook/build/blog/tags/net-5/index.html index 3a44baea021..1c731a63f3d 100644 --- a/handbook/build/blog/tags/net-5/index.html +++ b/handbook/build/blog/tags/net-5/index.html @@ -6,7 +6,7 @@ Posts tagged ".net5" | Fur - + @@ -25,7 +25,7 @@

    1 post tagged with ".net5"

    View All Tags

    Fur 介绍

    dotnet中国

    dotnet中国

    为中国 .NET 开发者提供优质的资讯和技术分享。

    star fork GitHub stars GitHub forks GitHub license

    Fur.NET 5 平台下极易入门、极速开发的 Web 应用框架。

    🍕 名字的由来

    故事是这样子的:

    起初,想开发一个极易入门、极易维护的框架,开发理念为:一切从简,只为了更懒

    所以自然而然想到了:Lazier,也就是 更懒 的意思。但是 更懒更烂 读音相近且中文名没有特色,对此换名问题我苦恼了好几天。

    刚好有一次我在博客园中帮一个博友解答问题,解决后博友赞扬我对 .NET Core 颇有了解,我就顺嘴回答了一句:“略懂皮毛”

    就这时,脑瓜子灵机一动,干脆起名为:“皮毛”?英文单词 Fur [fɜː(r)]”,单词又短而且中文读音既俗气又顺口。😄😎

    所以,Fur 就诞生了。

    之后就有了 “小僧不才,略懂皮毛(Fur)。” 广告语 和 chinadot.net 域名。

    🍔 关于 LOGO

    Fur LOGO 设计由 F U R 三个单词组成:

    我相信很多人看到 Fur 的 LOGO 时都会问:“为什么选择奶牛?”,因为 那些年吹过的牛逼都实现了 🐮

    之所以选择 奶牛 是因为 具有脚踏实地,任劳任怨的做事风格,同时 奶牛 意味着丰富的营养价值,正如 Fur 所能带给你的。

    🍟 文档地址

    https://chinadot.net

    - + diff --git a/handbook/build/blog/tags/net/index.html b/handbook/build/blog/tags/net/index.html index e8d0548f522..9ba597c7700 100644 --- a/handbook/build/blog/tags/net/index.html +++ b/handbook/build/blog/tags/net/index.html @@ -6,7 +6,7 @@ Posts tagged ".net" | Fur - + @@ -25,7 +25,7 @@

    1 post tagged with ".net"

    View All Tags

    Fur 介绍

    dotnet中国

    dotnet中国

    为中国 .NET 开发者提供优质的资讯和技术分享。

    star fork GitHub stars GitHub forks GitHub license

    Fur.NET 5 平台下极易入门、极速开发的 Web 应用框架。

    🍕 名字的由来

    故事是这样子的:

    起初,想开发一个极易入门、极易维护的框架,开发理念为:一切从简,只为了更懒

    所以自然而然想到了:Lazier,也就是 更懒 的意思。但是 更懒更烂 读音相近且中文名没有特色,对此换名问题我苦恼了好几天。

    刚好有一次我在博客园中帮一个博友解答问题,解决后博友赞扬我对 .NET Core 颇有了解,我就顺嘴回答了一句:“略懂皮毛”

    就这时,脑瓜子灵机一动,干脆起名为:“皮毛”?英文单词 Fur [fɜː(r)]”,单词又短而且中文读音既俗气又顺口。😄😎

    所以,Fur 就诞生了。

    之后就有了 “小僧不才,略懂皮毛(Fur)。” 广告语 和 chinadot.net 域名。

    🍔 关于 LOGO

    Fur LOGO 设计由 F U R 三个单词组成:

    我相信很多人看到 Fur 的 LOGO 时都会问:“为什么选择奶牛?”,因为 那些年吹过的牛逼都实现了 🐮

    之所以选择 奶牛 是因为 具有脚踏实地,任劳任怨的做事风格,同时 奶牛 意味着丰富的营养价值,正如 Fur 所能带给你的。

    🍟 文档地址

    https://chinadot.net

    - + diff --git a/handbook/build/blog/tags/netcore/index.html b/handbook/build/blog/tags/netcore/index.html index badcf783539..71b87e2f97b 100644 --- a/handbook/build/blog/tags/netcore/index.html +++ b/handbook/build/blog/tags/netcore/index.html @@ -6,7 +6,7 @@ Posts tagged ".netcore" | Fur - + @@ -25,7 +25,7 @@

    1 post tagged with ".netcore"

    View All Tags

    Fur 介绍

    dotnet中国

    dotnet中国

    为中国 .NET 开发者提供优质的资讯和技术分享。

    star fork GitHub stars GitHub forks GitHub license

    Fur.NET 5 平台下极易入门、极速开发的 Web 应用框架。

    🍕 名字的由来

    故事是这样子的:

    起初,想开发一个极易入门、极易维护的框架,开发理念为:一切从简,只为了更懒

    所以自然而然想到了:Lazier,也就是 更懒 的意思。但是 更懒更烂 读音相近且中文名没有特色,对此换名问题我苦恼了好几天。

    刚好有一次我在博客园中帮一个博友解答问题,解决后博友赞扬我对 .NET Core 颇有了解,我就顺嘴回答了一句:“略懂皮毛”

    就这时,脑瓜子灵机一动,干脆起名为:“皮毛”?英文单词 Fur [fɜː(r)]”,单词又短而且中文读音既俗气又顺口。😄😎

    所以,Fur 就诞生了。

    之后就有了 “小僧不才,略懂皮毛(Fur)。” 广告语 和 chinadot.net 域名。

    🍔 关于 LOGO

    Fur LOGO 设计由 F U R 三个单词组成:

    我相信很多人看到 Fur 的 LOGO 时都会问:“为什么选择奶牛?”,因为 那些年吹过的牛逼都实现了 🐮

    之所以选择 奶牛 是因为 具有脚踏实地,任劳任怨的做事风格,同时 奶牛 意味着丰富的营养价值,正如 Fur 所能带给你的。

    🍟 文档地址

    https://chinadot.net

    - + diff --git a/handbook/build/blog/welcome/index.html b/handbook/build/blog/welcome/index.html index a547ec07a89..d5b7cff1078 100644 --- a/handbook/build/blog/welcome/index.html +++ b/handbook/build/blog/welcome/index.html @@ -6,7 +6,7 @@ Fur 介绍 | Fur - + @@ -24,7 +24,7 @@

    Fur 介绍

    dotnet中国

    dotnet中国

    为中国 .NET 开发者提供优质的资讯和技术分享。

    star fork GitHub stars GitHub forks GitHub license

    Fur.NET 5 平台下极易入门、极速开发的 Web 应用框架。

    🍕 名字的由来

    故事是这样子的:

    起初,想开发一个极易入门、极易维护的框架,开发理念为:一切从简,只为了更懒

    所以自然而然想到了:Lazier,也就是 更懒 的意思。但是 更懒更烂 读音相近且中文名没有特色,对此换名问题我苦恼了好几天。

    刚好有一次我在博客园中帮一个博友解答问题,解决后博友赞扬我对 .NET Core 颇有了解,我就顺嘴回答了一句:“略懂皮毛”

    就这时,脑瓜子灵机一动,干脆起名为:“皮毛”?英文单词 Fur [fɜː(r)]”,单词又短而且中文读音既俗气又顺口。😄😎

    所以,Fur 就诞生了。

    之后就有了 “小僧不才,略懂皮毛(Fur)。” 广告语 和 chinadot.net 域名。

    🍔 关于 LOGO

    Fur LOGO 设计由 F U R 三个单词组成:

    我相信很多人看到 Fur 的 LOGO 时都会问:“为什么选择奶牛?”,因为 那些年吹过的牛逼都实现了 🐮

    之所以选择 奶牛 是因为 具有脚踏实地,任劳任怨的做事风格,同时 奶牛 意味着丰富的营养价值,正如 Fur 所能带给你的。

    🍟 文档地址

    https://chinadot.net

    🌭 开源地址

    🍿 Docker 镜像

    docker run --name fur -p 5000:80 monksoul/fur:v1.0.0-2020.10.07

    🥞 架构设计

    正在整理中...

    🥝 功能模块

    🥐 框架依赖

    Fur 为了追求极速入门,极致性能,尽可能的不使用或减少第三方依赖。目前 Fur 仅集成了以下三个依赖:

    麻雀虽小五脏俱全。Fur 即使只集成了这三个依赖,但是主流的 依赖注入/控制反转AOP 面向切面编程,事件总线数据验证数据库操作 等等一个都不少。

    🥗 环境要求

    • Visual Studio 2019 Preview 16.8 +
    • .NET 5 SDK +
    • .Net Standard 2.1 +

    🥪 支持平台

    • 运行环境
      • Windows
      • Linux
      • MacOS
      • Docker/K8S/K3S/Rancher
    • 数据库
      • SqlServer
      • Sqlite
      • Azure Cosmos
      • MySql
      • PostgreSQL
      • InMemoryDatabase
      • Oracle
      • Firebird
      • 达梦数据库
    • 应用部署
      • Kestrel
      • Nginx
      • Jexus
      • IIS
      • Apache
      • PM2
      • Supervisor
      • 单文件
      • 容器(Docker/K8S/K3S/Rancher)

    🍖 关于性能

    Fur 目前采用 Visual Studio 2019 Preview 16.8 自带性能测试和 JMeter 进行测试,由于篇幅有限,只贴部分测试图,测试结果如下:


    🍚 关于作者

    一个拥有 12 年开发经验 .NETer。喜欢分享,喜欢新技术,在互联网多个技术领域皆有涉猎。

    🍤 项目成员

    🎈 欢迎更多的开发者加入 Fur 大家庭。

    🍝 谁在使用

    • 百签科技(广东)有限公司
    • 码为科技(广州)有限公司
    • 广州启顺国际货运代理有限公司
    • 森丰供应链服务(广州)有限公司
    • 中山赢友网络科技有限公司
    • 中山模思软件科技有限公司
    • 珠海市恒泰新软件有限责任公司
    • 珠海思诺锐创软件有限公司
    • 深圳市易胜科技有限公司
    • 重庆虫儿飞科技有限公司
    • 重庆林木森科技有限公司

    如果您的项目使用到 Fur 开发,可以告诉我们。

    🍻 贡献代码

    Fur 遵循 Apache-2.0 开源协议,欢迎大家提交 PRIssue

    如果要为项目做出贡献,请查看贡献指南。

    🍍 捐赠列表

    注:排序按捐赠顺序书写

    捐赠人昵称捐赠金额(元)附语
    🤴 爱吃油麦菜100感谢您的开源项目!
    👳‍♂️ 麦壳饼200感谢您的开源项目!
    👨 Sun100感谢您的开源项目!
    👶 d61761720感谢您的开源项目!
    👦 Diqiguoji00816.66见贤思齐
    👲 nodyang100感谢您的开源项目!
    👳‍♀️ mictxd100吹过的牛都实现。
    🧓 欧流全10希望将来超越 Spring
    👨‍⚕️ lionkon10...看了框架感觉拿来学习是很不错的...

    非常感谢您们的支持,正是因为您们,中国开源才可以越走越远,Fur 越走越远。

    🥔 QQ 交流群

    🧆 友情链接

    👉 Fur 👉 SqlSugar 👉 Layx 👉 t-io

    - + diff --git a/handbook/build/docs/aop/index.html b/handbook/build/docs/aop/index.html index 08a3d973b1e..7312c85d107 100644 --- a/handbook/build/docs/aop/index.html +++ b/handbook/build/docs/aop/index.html @@ -6,7 +6,7 @@ 20. 拦截切面 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/handbook/build/docs/appstartup/index.html b/handbook/build/docs/appstartup/index.html index c21581d3052..af62b6a0b24 100644 --- a/handbook/build/docs/appstartup/index.html +++ b/handbook/build/docs/appstartup/index.html @@ -4,9 +4,9 @@ -3. 应用启动 | Fur +3. 应用启动 | Fur - + @@ -20,13 +20,38 @@ - +
    -
    +

    3. 应用启动

    3.1 Startup

    Startup 类是 ASP.NET Core 应用程序启动默认调用的类,该类是在 Program.cs 中配置:

    Fur.Web.Entry\Program.cs
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Hosting;
    +
    namespace Fur.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>();
    });
    }
    }
    }

    3.1.1 Startup 两个重要方法

    Startup 默认有两个重要的方法:

    • ConfigureServices:配置应用所需服务,在该方法中可以添加应用所需要的功能或服务
    • Configure:配置应用请求处理管道

    默认代码如下:

    Fur.Web.Entry\Startup.cs
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.DependencyInjection;
    +
    namespace Fur.Web.Entry
    {
    public class Startup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    }
    +
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
    }
    }
    }

    在这里,不打算详细讲 Startup 类的具体功能和作用。

    了解更多

    想了解更多 Startup 知识可查阅 ASP.NET Core - Startup 类 章节。

    3.2 AppStartup

    Fur 框架中,提供了更为灵活的 Startup 类配置方式,无需在 Web 启用层 中配置,可将配置放到任何项目层。

    可能会有读者有疑问,为什么要多此一举呢?原因有几点:

    • Startup 类默认和 Web 应用层 绑定在一起,这样就会导致如果我创建了新的 Web 应用层Startup 又要重新配置
    • 随着业务的增长,需要集成越来越多的第三方服务,这时候 Startup 类就会变得越来越臃肿,难以维护
    • Startup 类无法其他项目类型进行共用

    所以,Fur 提供了更加灵活的配置方式:AppStartup

    3.2.1 如何配置 AppStartup

    AppStartup 是一个抽象的空类,没有任何定义成员。正是因为这样,才提供更加灵活的配置方式。

    3.2.2 AppStartup 约定

    AppStartup 派生类只有两个小约定:

    • 任何公开、非静态、返回值为 void 且方法第一个参数是 IServiceCollection 类型,那么他就是一个 ConfigureServices 方法
    • 任何公开、非静态、返回值为 void 且方法第一个参数是 IApplicationBuilder 类型,第二个参数是 IWebHostEnvironment 类型,那么他就是一个 Configure 方法

    所以,我们可以自由的编写方法,只要遵循约定即可,如:

    using Microsoft.Extensions.DependencyInjection;
    +
    namespace Fur.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.2.3 AppStartup 配置顺序

    默认情况下,AppStartup 配置顺序由所在程序集的名称进行正序调用,如果我们需要配置执行顺序,只需要在 AppStartup 派生类中贴 [AppStartup(order)] 特性即可。

    order 数值越大,约在前面调用,如:

    using Microsoft.Extensions.DependencyInjection;
    +
    namespace Fur.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 Fur.EntityFramework.Core
    {
    [AppStartup(9)]
    public class SecondStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    }
    +
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
    }
    }
    }

    FirstStartup 会在 SecondStartup 之前调用。

    3.2.4 AppStartup 方法调用顺序

    AppStartup 方法调用顺序和方法的书写先后有关,越在前面的方法越先调用。

    3.3 框架默认 AppStartup 实现

    Fur 框架默认在每一个项目层中都创建了一个 AppStartup 派生类,方便大家配置。如:

    • FurStartup.csFur 框架核心启动类(通常无需配置)
    • FurApplicationStartup.cs:业务服务启动类
    • FurCoreStartup.cs:应用核心功能启动类
    • FurEntityFrameworkCoreStartup.cs:数据库相关启动类
    • FurWebCoreStartup.csWeb 核心启动配置类

    3.4 Startup 配置最佳实践

    建议 Web 启动层的 Startup.cs 保持为空方法体,如:

    Fur.Web.Entry\Startup.cs
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.DependencyInjection;
    +
    namespace Fur.Web.Entry
    {
    public class Startup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    }
    +
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
    }
    }
    }

    将所有 Web 应用层 配置迁移到 FurWebCoreStartup.cs 中,如:

    Fur.Web.Core\FurWebCoreStartup.cs
    using Fur.UnifyResult;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    +
    namespace Fur.Web.Core
    {
    [AppStartup(800)]
    public sealed class FurWebCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddCorsAccessor();
    +
    services.AddSpecificationDocuments();
    services.AddControllers()
    .AddDynamicApiControllers()
    .AddDataValidation()
    .AddFriendlyException()
    .AddUnifyResult<RESTfulResult, RESTfulResultProvider>();
    }
    +
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
    if (env.IsDevelopment())
    {
    app.UseDeveloperExceptionPage();
    }
    +
    app.UseHttpsRedirection();
    +
    app.UseRouting();
    +
    app.UseCorsAccessor();
    +
    app.UseAuthentication();
    app.UseAuthorization();
    +
    app.UseSpecificationDocuments();
    +
    app.UseEndpoints(endpoints =>
    {
    endpoints.MapControllers();
    });
    }
    }
    }

    这样,后续更换 Web 应用层 也无需重新配置 Startup.cs

    3.5 关于 appsettings.json

    在默认情况下,ASP.NET Core 配置放在 appsettings.json 中配置,但是这样的方式和 Startup.cs 配置一样的道理,一旦我们更换了 Web 应用层,那么 appsettings.json 又要重新配置一次。

    所以,Fur 框架提供了更加灵活的方式配置 appsettings.json只需要在任何项目层根目录下创建 .json 文件即可

    Fur 框架最后会自动合并所有分散的配置文件。

    如我们在 Fur.EntityFramework.Core 层创建 dbsettings.json 配置数据库连接字符串,如:

    Fur.EntityFramework.Core\dbsettings.json
    {
    "ConnectionStrings": {
    "DbConnectionString": "Server=localhost;Database=Fur;User=sa;Password=000000;MultipleActiveResultSets=True;",
    "Sqlite3ConnectionString": "Data Source=./Fur.db"
    }
    }

    无需在 appsettings.json 中配置,下面是 appsettings.json 默认代码:

    {
    "Logging": {
    "LogLevel": {
    "Default": "Information",
    "Microsoft": "Warning",
    "Microsoft.Hosting.Lifetime": "Information",
    "Microsoft.EntityFrameworkCore": "Information"
    }
    },
    "AllowedHosts": "*"
    }

    这样我们把配置文件分散在不同项目层之后,就可以实现共用和共享了。

    3.6 神奇的 Inject()

    Inject() 方法是 Fur 框架提供的最小侵入式的方法,可以让任何 ASP.NET Core Web项目瞬间支持所有 Fur 框架特性。

    我们创建了新的 Web 项目,只需要两个步骤即可:

    • 添加 Fur.Web.Core 项目引用
    • Program.cs 中调用即可

    如:

    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Hosting;
    +
    namespace Fur.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>();
    });
    }
    }
    }

    非常简单吧。我们后续创建任何 MVCRazorPagesBlazor 项目只需要添加 Fur.Web.Core 引用和调用 Inject() 即可。

    3.7 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + @@ -40,6 +65,6 @@ - + \ 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 0f3975f30f6..6e9adecfcb9 100644 --- a/handbook/build/docs/auth-control/index.html +++ b/handbook/build/docs/auth-control/index.html @@ -6,7 +6,7 @@ 14. 安全鉴权 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/handbook/build/docs/author/index.html b/handbook/build/docs/author/index.html index 95e4d0d17de..09a3067e04f 100644 --- a/handbook/build/docs/author/index.html +++ b/handbook/build/docs/author/index.html @@ -6,7 +6,7 @@ 1.3 关于作者 | Fur - + @@ -26,7 +26,7 @@

    1.3 关于作者

    互联网账号

    • 百小僧
    • Monk/MonkSoul

    技术能力

    自 2008 年 接触 IT 这个行业也有十余年了,在 后端(.NET/.NET Core/Java/PHP)、移动端(Xamarin/小程序/Java/Objective-C)、桌面端(WinForm/WPF/Electron)、前端(React/Vue/Angular/Node)等主流领域略知一二。

    同时在技术培训领域也多有涉足。

    职业情况

    目前经营一家自己创办的软件科技公司,主要销售自主研发的 ERP 产品。

    吃不起饭的时候也会接外包项目。

    兴趣爱好

    是个吃货,喜欢看抖音,看动漫,看美剧,看博客园、看开源中国。

    对新技术颇感兴趣,喜欢开源事业,喜欢分享技术。

    个人主页

    https://gitee.com/monksoul

    https://github.com/monksoul

    - + diff --git a/handbook/build/docs/cache/index.html b/handbook/build/docs/cache/index.html index 9c27c5d4363..24ac4c1f4e4 100644 --- a/handbook/build/docs/cache/index.html +++ b/handbook/build/docs/cache/index.html @@ -6,7 +6,7 @@ 13. 分布式缓存 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/handbook/build/docs/configuration/index.html b/handbook/build/docs/configuration/index.html index cc0318de9f5..2aeed5752fd 100644 --- a/handbook/build/docs/configuration/index.html +++ b/handbook/build/docs/configuration/index.html @@ -6,7 +6,7 @@ 4.1 配置 | Fur - + @@ -29,7 +29,7 @@
    namespace Fur.Web.Entry
    {
    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
    // 启动自动扫描配置文件并注入,无需手动添加配置
    .UseSetting(WebHostDefaults.HostingStartupAssembliesKey, nameof(Fur))
    .UseStartup<Startup>();
    });
    }
    }

    读取 emailsetting.json 配置

    读取自定义配置文件和读取 appsettings.json 一致,系统会自动从多个配置文件中读取输入,如:

    var smtpServer = App.Configuration["outlook:smtp:server"]; // => smtp.office365.com

    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["AppInfo"];
    ChangeToken.OnChange(() => appInfoConfiguration.GetReloadToken(), () =>
    {
    var name = appInfoConfiguration["Name"]; // 实时的最新值
    var version = appInfoConfiguration["Version"]; // 实时的最新值
    });

    4.1.7 配置的优缺点

    优点

    • 能够在系统运行时快速读取
    • 无需额外配置

    缺点

    • 存在重复读取
    • 通过硬编码字符串读取,容易出错
    • 不能设置默认值
    • 不能在运行环境中动态配置
    • 不能验证配置有效性
    • 不支持更改通知

    4.1.8 配置使用场景

    如果只需要一次性读取配置信息,则使用配置,否则应该使用 《4.2 选项》代替。

    4.1.9 反馈与建议

    与我们交流

    给 Fur 提 Issue


    了解更多

    想了解更多 配置 知识可查阅 ASP.NET Core - 配置 章节。

    - + diff --git a/handbook/build/docs/contribute/index.html b/handbook/build/docs/contribute/index.html index 08123d6e336..cdc5bfe9b75 100644 --- a/handbook/build/docs/contribute/index.html +++ b/handbook/build/docs/contribute/index.html @@ -6,7 +6,7 @@ 28. 贡献指南 | Fur - + @@ -26,7 +26,7 @@ - + diff --git a/handbook/build/docs/cors/index.html b/handbook/build/docs/cors/index.html index d145f43ac8b..92f20f56876 100644 --- a/handbook/build/docs/cors/index.html +++ b/handbook/build/docs/cors/index.html @@ -6,7 +6,7 @@ 15. CORS 跨域 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/handbook/build/docs/data-validation/index.html b/handbook/build/docs/data-validation/index.html index afe9d1ba1ad..a6011b9e8c8 100644 --- a/handbook/build/docs/data-validation/index.html +++ b/handbook/build/docs/data-validation/index.html @@ -6,7 +6,7 @@ 8. 数据校验 | Fur - + @@ -78,7 +78,7 @@
    namespace Fur.Application
    {
    public class FurAppService : IDynamicApiController
    {
    [TypeFilter(typeof(DataValidationFilter))]
    public TestDto Post(TestDto testDto)
    {
    return testDto;
    }
    }
    }

    8.9.4 [ApiController] 控制器范围验证

    [ApiController]Mvc 提供的控制器范围(含所有动作方法)的验证。

    using Microsoft.AspNetCore.Mvc;
    namespace Fur.Web.Entry.Controllers
    {
    [ApiController]
    public class MvcController : Controller
    {
    public IActionResult Index()
    {
    return View();
    }
    }
    }

    8.10 MiniProfiler 查看

    如下图所示:

    8.10 多语言支持

    文档整理中...

    8.11 验证模型提供器

    文档整理中...

    8.12 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/dbcontext-Interceptor/index.html b/handbook/build/docs/dbcontext-Interceptor/index.html index 4dbff358e91..b392c748479 100644 --- a/handbook/build/docs/dbcontext-Interceptor/index.html +++ b/handbook/build/docs/dbcontext-Interceptor/index.html @@ -6,7 +6,7 @@ 9.24 数据库操作拦截器 | Fur - + @@ -20,11 +20,11 @@ - +
    -

    9.24 数据库操作拦截器

    9.24.1 数据库拦截器

    Fur 框架提供三种数据库操作拦截器,可以通过拦截器动态修改数据库连接字符串,动态修改sql,动态更改参数等操作。

    目前支持这三种拦截器:

    • DbConnectionInterceptor:数据库连接拦截器
    • DbCommandInterceptor:数据库执行 Sql 拦截器
    • SaveChangesInterceptor:提交到数据库拦截器

    9.24.2 支持拦截类型

    9.24.2.1 DbConnectionInterceptor

    using Microsoft.EntityFrameworkCore.Diagnostics;
    using System.Data.Common;
    using System.Threading;
    using System.Threading.Tasks;
    +

    9.24 数据库操作拦截器

    9.24.1 数据库拦截器

    Fur 框架提供三种数据库操作拦截器,可以通过拦截器动态修该数据库连接字符串,动态修改sql,动态更改参数等操作。

    目前支持这三种拦截器:

    • DbConnectionInterceptor:数据库连接拦截器
    • DbCommandInterceptor:数据库执行 Sql 拦截器
    • SaveChangesInterceptor:提交到数据库拦截器

    9.24.2 支持拦截类型

    9.24.2.1 DbConnectionInterceptor

    using Microsoft.EntityFrameworkCore.Diagnostics;
    using System.Data.Common;
    using System.Threading;
    using System.Threading.Tasks;
    namespace Fur.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);
    }
    @@ -59,7 +59,7 @@
    // 提交数据库失败
    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.3 注册自定义过滤器

    定义好过滤器之后,我们需要在数据库上下文中注册:

    services.AddSqlitePool<FurDbContext>(interceptors: new IInterceptor[] {
    new SqlConnectionProfilerInterceptor(),
    new DbContextSaveChangesInterceptor(),
    new SqlCommandProfilerInterceptor()
    });

    9.24.4 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + @@ -73,6 +73,6 @@ - + \ 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 a99f9fabef5..806daf11e82 100644 --- a/handbook/build/docs/dbcontext-add-or-update/index.html +++ b/handbook/build/docs/dbcontext-add-or-update/index.html @@ -6,7 +6,7 @@ 9.7 新增或更新操作 | Fur - + @@ -104,7 +104,7 @@
    // 示例七
    await user.InsertOrUpdateExcludeNowAsync(new[] { u=>u.Name, u=>u.Age});
    // 示例八
    await user.InsertOrUpdateExcludeNowAsync(new[] {"Age", "Name"});

    9.5.7 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/dbcontext-add/index.html b/handbook/build/docs/dbcontext-add/index.html index 9ac9e9a8d5a..cc4c5cf9bf2 100644 --- a/handbook/build/docs/dbcontext-add/index.html +++ b/handbook/build/docs/dbcontext-add/index.html @@ -6,7 +6,7 @@ 9.5 新增操作 | Fur - + @@ -55,7 +55,7 @@
    // 示例二
    await repository.InsertNowAsync(new List<User> { user, user2 });
    // 示例三
    await repository.InsertNowAsync(new[] {user, user2 });
    小知识

    所有带 Now 结尾的表示立即提交到数据库,也就是立即调用 SaveChangesSaveChangesAsync

    9.5.5 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/dbcontext-audit/index.html b/handbook/build/docs/dbcontext-audit/index.html index d70e7c95183..cedece50da7 100644 --- a/handbook/build/docs/dbcontext-audit/index.html +++ b/handbook/build/docs/dbcontext-audit/index.html @@ -6,7 +6,7 @@ 9.22 审计日志 | Fur - + @@ -39,7 +39,7 @@
    object oldValue = null;
    // 如果是新增数据,则 databaseValues 为空,所以需要判断一下
    if (databaseValues != null)
    {
    oldValue = databaseValues[propName];
    }
    // 插入审计日志表
    dbContext.Audits.Add(new Audit
    {
    Table = entityType.Name, // 表名
    Column = propName, // 更新的列
    NewValue = newValue, // 新值
    OldValue = oldValue, // 旧值
    CreatedTime = DateTime.Now, // 操作时间
    UserId = userId, // 操作人
    Operate = entity.State.ToString(); // 操作方式:新增、更新、删除
    });
    }
    }
    }
    }
    }
    小知识

    如果对性能有所要求,那么建议审计日志通过 日志组件 写入数据库,如,通过 Nlog、Log4Net 这些等:

    // 插入审计日志表
    dbContext.Audits.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.4 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/dbcontext-batch/index.html b/handbook/build/docs/dbcontext-batch/index.html index 3616198d4dd..ce99f0ad13e 100644 --- a/handbook/build/docs/dbcontext-batch/index.html +++ b/handbook/build/docs/dbcontext-batch/index.html @@ -6,7 +6,7 @@ 9.9 批量操作 | Fur - + @@ -34,7 +34,7 @@
    // 根据条件批量更新
    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 批量操作性能

    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 反馈与建议

    与我们交流

    给 Fur 提 Issue


    了解更多

    想了解更多 EFCore.BulkExtensions 知识可查阅 EFCore.BulkExtensions 开源仓库

    - + diff --git a/handbook/build/docs/dbcontext-code-first/index.html b/handbook/build/docs/dbcontext-code-first/index.html index c8ff7671a86..8bf60cf4643 100644 --- a/handbook/build/docs/dbcontext-code-first/index.html +++ b/handbook/build/docs/dbcontext-code-first/index.html @@ -6,7 +6,7 @@ 9.20 模型生成数据库 | Fur - + @@ -30,7 +30,7 @@
    /// <summary>
    /// 年龄
    /// </summary>
    public int Age { get; set; }
    /// <summary>
    /// 住址
    /// </summary>
    public string Address { get; set; }
    }
    }
    实体约定

    所有数据库实体必须直接或间接继承 IEntity 接口。

    9.20.2.2 打开 程序包管理控制台

    9.20.2.3 切换默认项目

    程序包管理控制台 默认项目设置为 Fur.Database.Migrations

    9.20.2.4 创建模型版本

    Add-Migration v1.0.0
    特别说明

    v1.0.0 是此处数据库更改的版本号,可以写任何字符串,但推荐写版本号,每次 +1

    最终命令如下:

    PM> Add-Migration v1.0.0
    Build 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 'FurDbContext' using provider 'Microsoft.EntityFrameworkCore.Sqlite' with options: SensitiveDataLoggingEnabled DetailedErrorsEnabled MaxPoolSize=100 MigrationsAssembly=Fur.Database.Migrations
    To undo this action, use Remove-Migration.
    PM>

    生成成功后,Fur.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 反馈与建议

    与我们交流

    给 Fur 提 Issue


    了解更多

    想了解更多 正向工厂 知识可查阅 EF Core - 管理数据库架构 章节。

    - + diff --git a/handbook/build/docs/dbcontext-db-first/index.html b/handbook/build/docs/dbcontext-db-first/index.html index d5d8dce184b..bee38639953 100644 --- a/handbook/build/docs/dbcontext-db-first/index.html +++ b/handbook/build/docs/dbcontext-db-first/index.html @@ -6,7 +6,7 @@ 9.19 数据库生成模型 | Fur - + @@ -56,7 +56,7 @@
    }
    }
    Fur Tools v1.0.0 全部实体生成成功!
    PM>

    9.13.4 命令参数配置

    Fur Tools Cli 支持多个参数配置,使用方法只需要在命令后面添加即可,如:

    &"../tools/cli.ps1" -Context 数据库上下文名 -ConnectionName 连接字符串Key

    支持参数如下:

    • -Tables:配置要生成的数据库表,数组类型,如果为空,则生成数据库所有表和视图。如:-Tables Person,PersonDetails
    • -Context:配置数据库上下文,默认 FurDbContext,如果有多个数据库上下文,则此参数必须配置
    • -ConnectionName:配置数据库连接字符串,对于 appsetting.json 中的 Key
    • -OutputDir:生成实体代码输出目录,默认为:./Fur.Core/Entities/
    • -DbProvider:数据库提供器,默认是 Microsoft.EntityFrameworkCore.SqlServer,其他数据库请指定对应程序集
      • SqlServerMicrosoft.EntityFrameworkCore.SqlServer
      • SqliteMicrosoft.EntityFrameworkCore.Sqlite
      • CosmosMicrosoft.EntityFrameworkCore.Cosmos
      • InMemoryDatabaseMicrosoft.EntityFrameworkCore.InMemory
      • MySqlPomelo.EntityFrameworkCore.MySql
      • PostgreSQLNpgsql.EntityFrameworkCore.PostgreSQL
      • OracleCitms.EntityFrameworkCore.Oracle
    • -EntryProject:Web 启用项目层名,默认 Fur.Web.Entry
    • -CoreProject:实体项目层名,默认 Fur.Core
    • -DbContextLocators:多数据库上下文定位器,默认 MasterDbContextLocator,支持多个,如:MasterDbContextLocator,MySqlDbContextLocator
    • -Product:解决方案默认前缀,如 Fur

    9.13.5 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/dbcontext-delete/index.html b/handbook/build/docs/dbcontext-delete/index.html index 769069cdcb5..21a0850ff19 100644 --- a/handbook/build/docs/dbcontext-delete/index.html +++ b/handbook/build/docs/dbcontext-delete/index.html @@ -6,7 +6,7 @@ 9.8 删除操作 | Fur - + @@ -71,7 +71,7 @@
    // 示例五
    await entity.FakeDeleteAsync();
    // 示例六
    await repository.UpdateIncludeAsync(user, u => u.IsDeleted);

    9.8.9 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/dbcontext-filter/index.html b/handbook/build/docs/dbcontext-filter/index.html index 1c4ea731502..61f77e4c5c2 100644 --- a/handbook/build/docs/dbcontext-filter/index.html +++ b/handbook/build/docs/dbcontext-filter/index.html @@ -6,7 +6,7 @@ 9.23 实体/全局查询筛选器 | Fur - + @@ -38,7 +38,7 @@
    // 创建表达式元素
    var parameter = Expression.Parameter(metadata.ClrType, "u");
    var properyName = Expression.Constant(nameof(Entity.IsDeleted));
    var propertyValue = Expression.Constant(false);
    // 构建表达式 u => EF.Property<bool>(u, "IsDeleted") == false
    var expressionBody = Expression.Equal(Expression.Call(typeof(EF), nameof(EF.Property), new[] { typeof(bool) }, parameter, properyName), propertyValue);
    var expression = Expression.Lambda(expressionBody, parameter);
    return expression;
    }
    }
    }
    小建议

    如果对动态构建 LambdaExpression 不熟悉的朋友,可以使用 System.Linq.Dynamic.Corehttps://github.com/zzzprojects/System.Linq.Dynamic.Core

    9.23.3 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/dbcontext-function/index.html b/handbook/build/docs/dbcontext-function/index.html index eaf7cf87b84..3d248275601 100644 --- a/handbook/build/docs/dbcontext-function/index.html +++ b/handbook/build/docs/dbcontext-function/index.html @@ -6,7 +6,7 @@ 9.14 函数操作 | Fur - + @@ -50,7 +50,7 @@
    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("Fur")).ToList();

    最终生成 Sql

    SELECT [g].Id, [g].Name, [g].Age, [g].Address
    FROM dbo.GetPersons(1) AS [g]
    WHERE [g].Name == N'Fur';

    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 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/dbcontext-hight-query/index.html b/handbook/build/docs/dbcontext-hight-query/index.html index 16e55da2860..1c64ebf229a 100644 --- a/handbook/build/docs/dbcontext-hight-query/index.html +++ b/handbook/build/docs/dbcontext-hight-query/index.html @@ -6,7 +6,7 @@ 9.11 高级查询操作 | Fur - + @@ -57,7 +57,7 @@
    namespace Fur.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<City> 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.12 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/dbcontext-locator/index.html b/handbook/build/docs/dbcontext-locator/index.html index 38025daf25c..baddfc31a50 100644 --- a/handbook/build/docs/dbcontext-locator/index.html +++ b/handbook/build/docs/dbcontext-locator/index.html @@ -6,7 +6,7 @@ 9.2 数据库上下文定位器 | Fur - + @@ -28,7 +28,7 @@
    namespace Fur.Core
    {
    public sealed class FurDbContextLocator : IDbContextLocator
    {
    }
    }

    9.2.4 默认数据库上下文定位器

    Fur 框架中已经提供了 MasterDbContextLocator 默认数据库上下文定位器,所以默认数据库上下文只需继承 AppDbContext<TDbContext> 即可。

    AppDbContext<TDbContext> 定义代码如下:

    using Fur.DependencyInjection;
    using Microsoft.EntityFrameworkCore;
    namespace Fur.DatabaseAccessor
    {
    /// <summary>
    /// 默认应用数据库上下文
    /// </summary>
    /// <typeparam name="TDbContext">数据库上下文</typeparam>
    [NonBeScan]
    public abstract class AppDbContext<TDbContext> : AppDbContext<TDbContext, MasterDbContextLocator>
    where TDbContext : DbContext
    {
    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="options"></param>
    public AppDbContext(DbContextOptions<TDbContext> options) : base(options)
    {
    }
    }
    }

    9.2.5 数据库上下文定位器支持对象

    目前数据库上下文支持以下多个对象:

    • AppDbContext<TEntity, TDbContextLocator>:数据上下文
    • IRepository<TEntity, TDbContextLocator:实体仓储
    • ISqlRepository<TDbContextLocator>: Sql 操作仓储
    • Func<Type, DbContext>:依赖注入获取数据库上下文
    • Entity<Tkey, TDbContextLocator> :实体配置
    • EntityBase<Tkey, TDbContextLocator1, ... TDbContextLocator8>:实体配置
    • EntityNotKey<TDbContextLocator1, ... TDbContextLocator8>:无键实体配置
    • IEntitySeedData<TEntity, TDbContextLocator1, ... TDbContextLocator8>:种子数据配置
    • IEntityTypeBuilder<TEntity, TDbContextLocator1, ... TDbContextLocator8>:实体类型构建器
    • IModelBuilderFilter<TDbContextLocator1, ... TDbContextLocator8>:模型构建筛选器
    • [QueryableFunction(DbContextLocators=Type[])]:查询函数

    9.2.6 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/dbcontext-multi-database/index.html b/handbook/build/docs/dbcontext-multi-database/index.html index 1094d2efd4d..91f0f12e258 100644 --- a/handbook/build/docs/dbcontext-multi-database/index.html +++ b/handbook/build/docs/dbcontext-multi-database/index.html @@ -6,7 +6,7 @@ 9.18 多数据库操作 | Fur - + @@ -43,7 +43,7 @@
    // 支持一个数据库
    public class Person: IEntity<MySqlDbContextLocator>
    {
    // ....
    }
    // 支持多个数据库
    public class Person: IEntity<MySqlDbContextLocator, SqliteDbContextLocator>
    {
    // ....
    }
    小知识

    所有的 实体依赖接口或抽象类 都支持泛型方式 指定 数据库上下文定位器,最多支持 8 个。

    9.18.3.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.4 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/dbcontext-proc/index.html b/handbook/build/docs/dbcontext-proc/index.html index 65979efce35..5360cca572a 100644 --- a/handbook/build/docs/dbcontext-proc/index.html +++ b/handbook/build/docs/dbcontext-proc/index.html @@ -6,7 +6,7 @@ 9.13 存储过程操作 | Fur - + @@ -119,7 +119,7 @@
    // 获取 RETURN 返回值
    var reval = result.ReturnValue;
    // 获取返回结果集
    var (list1,list2) = result.Result;
    关于异步

    Fur 框架每一个数据库操作都支持异步方式,由于篇幅有限,就不列举异步方式了。

    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 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/dbcontext-query/index.html b/handbook/build/docs/dbcontext-query/index.html index 6d2313192cb..0ca0d736e88 100644 --- a/handbook/build/docs/dbcontext-query/index.html +++ b/handbook/build/docs/dbcontext-query/index.html @@ -6,7 +6,7 @@ 9.10 查询操作 | Fur - + @@ -138,7 +138,7 @@
    // 示例二
    _testRepository.Where(u => u.Name.EndWith("Fur"));
    // 示例三
    _testRepository.Where(u => u.Name.Contains("Fur"));

    9.10.6.9 Case When

    数据库中的 Case When 实际上对应的是我们程序中的 三元表达式 ,也就是使用 三元表达式 即可自动生成 Case When 语句。

    9.10.7 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/dbcontext-read-write/index.html b/handbook/build/docs/dbcontext-read-write/index.html index f59163d466b..3105bda9b20 100644 --- a/handbook/build/docs/dbcontext-read-write/index.html +++ b/handbook/build/docs/dbcontext-read-write/index.html @@ -6,7 +6,7 @@ 9.26 读写分离/主从复制 | Fur - + @@ -20,7 +20,7 @@ - +
    @@ -28,7 +28,7 @@
    namespace Fur.EntityFramework.Core
    {
    /// <summary>
    /// 主库数据库上下文
    /// </summary>
    [AppDbContext("MasterConnectionString")]
    public class MasterDbContext : AppDbContext<MasterDbContext>
    {
    public MasterDbContext(DbContextOptions<MasterDbContext> options) : base(options)
    {
    }
    }
    }

    数据库连接字符串:

    {
    "ConnectionStrings": {
    "MasterConnectionString": "Server=localhost;Database=Fur;User=sa;Password=000000;MultipleActiveResultSets=True;"
    }
    }

    9.26.2.2 创建 从库 数据库上下文

    using Fur.Core;
    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    namespace Fur.EntityFramework.Core
    {
    /// <summary>
    /// 从库数据库上下文
    /// </summary>
    [AppDbContext("SlaveConnectionString")]
    public class SlaveDbContext : AppDbContext<SlaveDbContext, SlaveDbContextLocator>
    {
    public SlaveDbContext(DbContextOptions<SlaveDbContext> options) : base(options)
    {
    }
    }
    }
    特别注意

    多数据库操作除了默认数据库无需自定义 数据库上下文定位器,其他数据库都需要有数据库上下文定位器。如 SlaveDbContextLocator

    从库数据库上下文定位器:

    using Fur.DatabaseAccessor;
    namespace Fur.Core
    {
    /// <summary>
    /// 从库数据库上下文定位器
    /// </summary>
    public class SlaveDbContextLocator : IDbContextLocator
    {
    }
    }

    数据库连接字符串:

    {
    "ConnectionStrings": {
    "SlaveConnectionString": "Server=localhost;Database=FurSlave;User=sa;Password=000000;MultipleActiveResultSets=True;"
    }
    }

    9.26.2.3 注册 主从库 数据库上下文

    using Fur.Core;
    using Microsoft.Extensions.DependencyInjection;
    -
    namespace Fur.EntityFramework.Core
    {
    [Startup(600)]
    public sealed class FurEntityFrameworkCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddDatabaseAccessor(options =>
    {
    services.AddSqlServerPool<MasterDbContext>();
    services.AddSqlServerPool<SlaveDbContext, SlaveDbContextLocator>();
    });
    }
    }
    }

    9.26.2.4 创建 Person 实体

    由于 主从库 具有相同的数据库结构,所以实体也必须声明 主从库

    using Fur.DatabaseAccessor;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    +
    namespace Fur.EntityFramework.Core
    {
    [AppStartup(600)]
    public sealed class FurEntityFrameworkCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddDatabaseAccessor(options =>
    {
    services.AddSqlServerPool<MasterDbContext>();
    services.AddSqlServerPool<SlaveDbContext, SlaveDbContextLocator>();
    });
    }
    }
    }

    9.26.2.4 创建 Person 实体

    由于 主从库 具有相同的数据库结构,所以实体也必须声明 主从库

    using Fur.DatabaseAccessor;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    namespace Fur.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.26.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.26.2.6 使用例子

    using Fur.Core;
    using Fur.DatabaseAccessor;
    using Fur.DynamicApiController;
    using System.Collections.Generic;
    @@ -38,7 +38,7 @@
    /// <summary>
    /// 查询走从库
    /// </summary>
    /// <returns></returns>
    public List<Person> Get()
    {
    return _msRepository.Slave1<Person>().AsEnumerable();
    }
    }
    }

    9.26.3 主从复制

    主从复制:是一种数据备份的方案。

    简单来说,是使用两个或两个以上相同的数据库,将一个数据库当做主数据库,而另一个数据库当做从数据库。在主数据库中进行相应操作时,从数据库记录下所有主数据库的操作,使其二者一模一样。

    9.26.4 主从复制几种方式

    9.26.4.1 同步复制

    所谓的同步复制,意思是 Master 的变化,必须等待 Slave-1,Slave-2,...,Slave-n 完成后才能返回。 这样,显然不可取,比如,在 Web 前端页面上,用户增加了条记录,需要等待很长时间。

    9.26.4.2 异步复制

    如同 AJAX 请求一样。Master 只需要完成自己的数据库操作即可。至于 Slaves 是否收到二进制日志,是否完成操作,不用关心。(推荐方式)

    9.26.4.3 半同步复制

    Master 只保证 Slaves 中的一个操作成功,就返回,其他 Slave 不管。

    下面将使用 SqlServer 简单配置主从复制功能。

    9.26.5 SqlServer 主库配置

    9.26.5.1 添加 本地发布

    9.26.5.2 选择 分发服务器

    9.26.5.3 启用 代理

    9.26.5.4 发布数据库

    9.26.5.5 快照发布

    具体选择何种发布类型,视具体业务场景而定。

    9.26.5.6 选择发布项目

    9.26.5.7 配置分发计划

    9.26.5.8 配置安全设置

    9.26.5.9 完成配置

    9.26.6 SqlServer 从库配置

    9.26.6.1 添加 本地订阅

    9.26.6.2 选择 分发服务器

    9.26.6.3 选择 分发代理位置

    9.26.6.4 选择 订阅数据库

    9.26.6.5 选择 分发安全设置

    9.26.6.6 选择 同步计划

    9.26.6.7 完成订阅

    9.26.7 分发定义监视

    9.26.8 查看主从复制结果

    特别特性

    主从复制有一定迟延性,所以系统设计要有一定“容忍性"。

    9.26.9 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + @@ -52,6 +52,6 @@ - + \ 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 576661a77e1..2f1d4e5d846 100644 --- a/handbook/build/docs/dbcontext-repository/index.html +++ b/handbook/build/docs/dbcontext-repository/index.html @@ -6,7 +6,7 @@ 9.4 仓储模式 | Fur - + @@ -33,7 +33,7 @@
    // 其他更多数据库一样的操作

    另外任何仓储或实体配置都支持多个数据库同时操作

    仓储方式

    IRepository<Person, MsSqlDbContextLocator> mssqlRepository
    ISqlRepository<MsSqlDbContextLocator> mssqlRepository;

    动态 sql 方式

    "select * from person".Change<MsSqlDbContextLocator>().SqlQuery();

    实体配置方式

    public class User:Entity<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.5 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/dbcontext-seed-data/index.html b/handbook/build/docs/dbcontext-seed-data/index.html index 19a978c8624..dbd2f392a9b 100644 --- a/handbook/build/docs/dbcontext-seed-data/index.html +++ b/handbook/build/docs/dbcontext-seed-data/index.html @@ -6,7 +6,7 @@ 9.21 实体种子数据 | Fur - + @@ -32,7 +32,7 @@
    namespace Fur.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 多个数据库种子数据

    Fur 提供泛型的方式支持多个数据库种子数据设定,如:

    using Fur.DatabaseAccessor;
    using System.Collections.Generic;
    namespace Fur.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 反馈与建议

    与我们交流

    给 Fur 提 Issue


    了解更多

    想了解更多 数据种子 知识可查阅 EF Core - 数据种子设定 章节。

    - + diff --git a/handbook/build/docs/dbcontext-sql-proxy/index.html b/handbook/build/docs/dbcontext-sql-proxy/index.html index 4854c467707..26eac2a078c 100644 --- a/handbook/build/docs/dbcontext-sql-proxy/index.html +++ b/handbook/build/docs/dbcontext-sql-proxy/index.html @@ -6,7 +6,7 @@ 9.17 Sql 高级代理 | Fur - + @@ -76,7 +76,7 @@
    namespace Fur.Application
    {
    public interface ISql : ISqlDispatchProxy
    {
    [SqlFunction("FN_Name")] // 标量函数
    string GetValue(MyParam dto);
    [SqlProcedure("FN_Name")] // 表值函数
    List<Person> GetPersons(int id);
    }
    }
    补充说明

    Sql 代理会自动判断返回值然后自动执行特定函数类型。

    9.17.6 为什么用它?

    通过上面的例子大家就可以了解,这种方式操作 sql 非常简单,而且极易维护。大家不用去关系返回值,关心用哪个方法,所有东西会自动给你处理好。

    所以,如果需要用 Sql 操作,推荐使用 Sql 高级代理。

    9.17.7 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/dbcontext-sql-template/index.html b/handbook/build/docs/dbcontext-sql-template/index.html index b50eed95925..1cb4de377a0 100644 --- a/handbook/build/docs/dbcontext-sql-template/index.html +++ b/handbook/build/docs/dbcontext-sql-template/index.html @@ -6,7 +6,7 @@ 9.16 Sql 模板 | Fur - + @@ -28,7 +28,7 @@
    // 懒人方式
    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 u
    left join #(User.Detail) d on u.Id = d.UserId
    where id > @id");

    9.16.4 Sql 模板配置

    9.16.4.1 普通模式

    {
    "Select.User": "select * from User"
    }

    9.16.4.2 更多配置

    {
    "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 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/dbcontext-sql/index.html b/handbook/build/docs/dbcontext-sql/index.html index 2bd0ed7fbdd..f641a607eba 100644 --- a/handbook/build/docs/dbcontext-sql/index.html +++ b/handbook/build/docs/dbcontext-sql/index.html @@ -6,7 +6,7 @@ 9.15 Sql 操作 | Fur - + @@ -173,7 +173,7 @@
    // 不再举例子。。。。。。
    补充说明

    不管是那种方式操作 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.6 IRepository 操作

    IRepository 也能操作 sql,调用方法也是和上面一致的,如:

    var dataTable = repository.Sql().SqlQuery("select * from person");
    特别说明

    由于篇幅有限,不再列举所有例子。

    9.15.7 IRepository<TEntity> 操作

    IRepository<TEntity> 也能操作 sql,调用方法也是和上面一致的,如:

    var dataTable = personRepository.SqlQuery("select * from person");
    特别说明

    由于篇幅有限,不再列举所有例子。

    9.15.8 关于 Sql 参数

    所有 sql存储过程函数 参数都支持四种方式:

    • DbParameter[]:数组类型
    • new {}:匿名类型
    • new Class{}:强类型类型(支持复杂存储过程参数)
    • Dictionary<string,object> 类型
    小知识

    建议除了复杂的存储过程(带 OUTPUT/RETURN)的以外,所有参数建议使用 new {} 匿名类型,如果需要动态参数,则可以使用 Dictionary<string,object> 类型。

    9.15.9 多数据库 Sql 操作 💯 💛

    Fur 框架拥有非常灵活的多数据库操作方式,只需通过多数据库上下文定位器即可动态切换数据库。

    9.15.9.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.9.2 ISqlRepository 方式

    只需要通过 ISqlRepository<TDbContextLocator> 注入或通过 sqlRepository.Change<TDbContextLocator>() 切换。

    9.15.9.3 IRepository 方式

    只需要通过 repository.Change<TDbContextLocator>() 获取即可。

    9.15.9.4 IRepository<TEntity> 方式

    只需要通过 IRepository<TEntity, TDbContextLocator> 注入或通过 personRepository.Change<TEntity, TDbContextLocator>() 切换。

    9.15.10 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/dbcontext-update/index.html b/handbook/build/docs/dbcontext-update/index.html index bc1b945a3d8..ca008ef4ac2 100644 --- a/handbook/build/docs/dbcontext-update/index.html +++ b/handbook/build/docs/dbcontext-update/index.html @@ -6,7 +6,7 @@ 9.6 更新操作 | Fur - + @@ -198,7 +198,7 @@
    // 示例二
    await repository.UpdateNowAsync(new List<User> { user, user2 });
    // 示例三
    await repository.UpdateNowAsync(new[] {user, user2 });
    小知识

    所有带 Now 结尾的表示立即提交到数据库,也就是立即调用 SaveChangesSaveChangesAsync

    9.6.15 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/dbcontext-view/index.html b/handbook/build/docs/dbcontext-view/index.html index 098b9aee55b..6625ad5b679 100644 --- a/handbook/build/docs/dbcontext-view/index.html +++ b/handbook/build/docs/dbcontext-view/index.html @@ -6,7 +6,7 @@ 9.12 视图操作 | Fur - + @@ -34,7 +34,7 @@
    public FurService(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.AsAsyncEnumerable();
    return list;
    }
    }
    }
    小知识

    通过 .Constraint<TEntity,TDbContextLocator> 方法可以将仓储约束为特定仓储,如只读仓储,可读可写仓储,只新增仓储等。

    9.12.5 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/dbcontext/index.html b/handbook/build/docs/dbcontext/index.html index 81e3c4ee986..45abc1b3f1a 100644 --- a/handbook/build/docs/dbcontext/index.html +++ b/handbook/build/docs/dbcontext/index.html @@ -6,7 +6,7 @@ 9.1 数据库上下文 | Fur - + @@ -20,24 +20,24 @@ - +

    9.1 数据库上下文

    9.1.1 数据库上下文

    简单来说,数据库上下文是负责和数据库交互的对象,提供程序对数据库存取提供了大量的方法。

    Fur 框架中,默认集成了微软亲儿子:EntityFramework Core ,也就是通常数据库上下文指的是 DbContext 类或它的实现类。

    9.1.2 AppDbContext

    在我们实际项目开发过程中,使用 EFCore 提供的 DbContext 操作对象操作数据库有些繁琐和复杂,且默认不具备读写分离、多库等操作功能。

    所以,Fur 框架提供了 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 能够得到 Fur 框架更多的功能支持

    9.1.4 如何定义数据库上下文

    Fur 框架中了,提供了两种 AppDbContext 定义方式:

    • AppDbContext<TDbContext> 操作默认数据库
    • AppDbContext<TDbContext, TDbContextLocator> 操作 N 个数据库

    其中 AppDbContext<TDbContext> 默认继承自 AppDbContext<TDbContext, TDbContextLocator>

    下面是数据库上下文创建的多个例子:

    9.1.4.1 创建默认数据库上下文

    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    namespace Fur.EntityFramework.Core
    {
    [AppDbContext("连接字符串或appsetting.json 键")]
    public class FurDbContext : AppDbContext<FurDbContext> // 继承 AppDbContext<> 类
    {
    /// <summary>
    /// 继承父类构造函数
    /// </summary>
    /// <param name="options"></param>
    public FurDbContext(DbContextOptions<FurDbContext> options) : base(options)
    {
    }
    }
    }

    9.1.4.2 创建其他数据库上下文

    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    namespace Fur.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)
    {
    }
    }
    }
    特别注意

    所有数据库上下文都应该在 Fur.EntityFramework.Core 项目中创建。关于 TDbContextLocator 将在下一章节 《9.2 数据库上下文定位器》阐述。

    9.1.5 配置连接字符串

    Fur 框架提供多种数据库连接字符串配置方式:

    • Startup 中添加服务:AddSqlServerPool<TDbContext>("连接字符串") 方式
    • 使用 [AppDbContext("连接字符串/Key")] 特性方式(只在 AppDbContext 实现类有效推荐
    • 通过重写 OnConfiguring(DbContextOptionsBuilder optionsBuilder) 配置

    9.1.5.1 Startup 方式配置

    Fur\framework\Fur.EntityFramework.Core\FurEntityFrameworkCoreStartup.cs
    using Fur.DependencyInjection;
    using Microsoft.Extensions.DependencyInjection;
    -
    namespace Fur.EntityFramework.Core
    {
    [Startup(600)]
    public sealed class FurEntityFrameworkCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    // 配置数据库上下文,支持N个数据库
    services.AddDatabaseAccessor(options =>
    {
    // 配置默认数据库
    options.AddDbPool<FurDbContext>(DbProvider.SqlServer, "连接字符串");
    +
    namespace Fur.EntityFramework.Core
    {
    [AppStartup(600)]
    public sealed class FurEntityFrameworkCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    // 配置数据库上下文,支持N个数据库
    services.AddDatabaseAccessor(options =>
    {
    // 配置默认数据库
    options.AddDbPool<FurDbContext>(DbProvider.SqlServer, "连接字符串");
    // 配置多个数据库,多个数据库必须指定数据库上下文定位器
    options.AddDbPool<SqliteDbContext, SqliteDbContextLocaotr>(DbProvider.Sqlite, "连接字符串");
    });
    }
    }
    }

    9.1.5.2 [AppDbContext] 方式配置

    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    namespace Fur.EntityFramework.Core
    {
    [AppDbContext("DbConnectionString")] // 支持 `appsetting.json` 名或 连接字符串
    public class FurDbContext : AppDbContext<FurDbContext>
    {
    /// <summary>
    /// 继承父类构造函数
    /// </summary>
    /// <param name="options"></param>
    public FurDbContext(DbContextOptions<FurDbContext> options) : base(options)
    {
    }
    }
    }
    小提示

    Fur 推荐使用此方式配置数据库连接字符串。

    [AppDbContext] 内置属性:

    • ConnectionString:数据库连接字符串,或配置文件中的路径(支持自定义配置查找),或 appsetting.jsonConnectionStrings 配置字符串
    • TablePrefix:当前数据库上下文表统一前缀
    • TableSuffix:当前数据库上下文表统一后缀

    9.1.5.3 OnConfiguring 方式配置

    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    namespace Fur.EntityFramework.Core
    {
    public class FurDbContext : AppDbContext<FurDbContext>
    {
    /// <summary>
    /// 继承父类构造函数
    /// </summary>
    /// <param name="options"></param>
    public FurDbContext(DbContextOptions<FurDbContext> options) : base(options)
    {
    }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
    base.OnConfiguring(optionsBuilder);
    -
    optionsBuilder.UseSqlServer("数据库连接字符串");
    }
    }
    }
    特别注意

    这三种方式可以同时使用,但是有优先级:[AppDbContext] -> Startup -> OnConfiguring(低到高)

    也就是 OnConfiguring 配置会覆盖 Startup 配置,Startup 配置会覆盖 [AppDbContext] 配置所配置的连接字符串。

    9.1.6 数据库上下文定义位置

    特别注意

    Fur 框架中,数据库上下文需定义在 Fur.EntityFramework.Core 中,且每一个数据库上下文都必须拥有唯一的 DbContextLocator 定位器

    9.1.7 数据库上下文注册

    数据库上下文配置好数据库连接字符串后,需要注册改数据库上下文,并指定数据库类型,如:

    Fur\framework\Fur.EntityFramework.Core\FurEntityFrameworkCoreStartup.cs
    using Fur.DatabaseAccessor;
    using Microsoft.Extensions.DependencyInjection;
    -
    namespace Fur.EntityFramework.Core
    {
    [Startup(600)]
    public sealed class FurEntityFrameworkCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddDatabaseAccessor(options =>
    {
    options.AddDbPool<FurDbContext>(DbProvider.Sqlite);
    });
    }
    }
    }

    如果有多个数据库操作,那么从第二个起,就需要绑定数据库上下文定位器,如:

    options.AddDbPool<FurDbContext>(DbProvider.Sqlite); // 第一个数据库
    +
    optionsBuilder.UseSqlServer("数据库连接字符串");
    }
    }
    }
    特别注意

    这三种方式可以同时使用,但是有优先级:[AppDbContext] -> Startup -> OnConfiguring(低到高)

    也就是 OnConfiguring 配置会覆盖 Startup 配置,Startup 配置会覆盖 [AppDbContext] 配置所配置的连接字符串。

    9.1.6 数据库上下文定义位置

    特别注意

    Fur 框架中,数据库上下文需定义在 Fur.EntityFramework.Core 中,且每一个数据库上下文都必须拥有唯一的 DbContextLocator 定位器

    9.1.7 数据库上下文注册

    数据库上下文配置好数据库连接字符串后,需要注册该数据库上下文,并指定数据库类型,如:

    Fur\framework\Fur.EntityFramework.Core\FurEntityFrameworkCoreStartup.cs
    using Fur.DatabaseAccessor;
    using Microsoft.Extensions.DependencyInjection;
    +
    namespace Fur.EntityFramework.Core
    {
    [AppStartup(600)]
    public sealed class FurEntityFrameworkCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddDatabaseAccessor(options =>
    {
    options.AddDbPool<FurDbContext>(DbProvider.Sqlite);
    });
    }
    }
    }

    如果有多个数据库操作,那么从第二个起,就需要绑定数据库上下文定位器,如:

    options.AddDbPool<FurDbContext>(DbProvider.Sqlite); // 第一个数据库
    options.AddDbPool<SecondDbContext, SecondDbContextDbContextLocator>(DbProvider.SqlServer); // 第二个数据库
    options.AddDbPool<ThirdDbContext, ThirdDbContextDbContextLocator>(DbProvider.SqlServer); // 第三个数据库

    9.1.8 动态数据库上下文对象

    Fur 框架中,数据库上下文是定义在 Fur.EntityFramework.Core 项目层,并且该层不被 Fur.ApplicationFur.Core 等层引用。

    所以就不能直接在 Fur.Application 项目层直接使用 Fur.EntityFramework.Core 定义的数据库上下文。

    Fur 为了解决这个问题,提供了两种方式处理:

    • respository.DbContext :当前数据库上下文对象,返回是 DbContext 抽象类型
    • respository.DynamicDbContext:当前数据库上下文对象,返回的是 dynamic 类型

    如果你只是想使用 DbContext 的功能,直接使用 respository.DbContext 即可,如:

    respository.DbContext.SaveChanges();

    如果你想能够获取具体的数据库上下文类型,如 MyDbContext,那么使用 respository.DynamicDbContext 就可以获取到具体的 MyDbContext 类型。如:

    var persons = respository.DynamicDbContext.Persons.Find(1);
    var users = respository.DynamicDbContext.Users;

    这样就可以直接操作 MyDbContext 定义的属性和方法了。

    9.1.9 反馈与建议

    与我们交流

    给 Fur 提 Issue


    了解更多

    想了解更多 数据库上下文 知识可查阅 EF Core - 配置 DbContext 章节。

    - + @@ -51,6 +51,6 @@ - + \ 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 2637b1b6df0..460e5796795 100644 --- a/handbook/build/docs/dependency-injection/index.html +++ b/handbook/build/docs/dependency-injection/index.html @@ -6,7 +6,7 @@ 11. 依赖注入/控制反转 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/handbook/build/docs/deploy/index.html b/handbook/build/docs/deploy/index.html index 936bef26748..ba223127cfc 100644 --- a/handbook/build/docs/deploy/index.html +++ b/handbook/build/docs/deploy/index.html @@ -6,7 +6,7 @@ 25. 托管部署 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/handbook/build/docs/devops/index.html b/handbook/build/docs/devops/index.html index 6c892320c9c..febe3254eca 100644 --- a/handbook/build/docs/devops/index.html +++ b/handbook/build/docs/devops/index.html @@ -6,7 +6,7 @@ 26. 持续部署集成 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/handbook/build/docs/dynamic-api-controller/index.html b/handbook/build/docs/dynamic-api-controller/index.html index a3edce468ff..f002d305df0 100644 --- a/handbook/build/docs/dynamic-api-controller/index.html +++ b/handbook/build/docs/dynamic-api-controller/index.html @@ -6,7 +6,7 @@ 5. 动态 WebAPI | Fur - + @@ -75,7 +75,7 @@
    namespace Fur.Web.Entry.Controllers
    {
    public class MvcController : ControllerBase
    {
    public string Get()
    {
    return nameof(Fur);
    }
    }
    }
    注意事项

    启用该配置后,如果 Mvc 控制器 没有任何 [Route] 特性,但是贴了 [ApiController] 特性将会报错。原因是 [ApiController] 特性内部做了路由特性检测。所以建议使用 [ApiDataValidation] 代替。

    查看 ASP.NET Core - ApiBehaviorApplicationModelProvider 源码

    5.11 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/entity/index.html b/handbook/build/docs/entity/index.html index 49246b92779..8966083a390 100644 --- a/handbook/build/docs/entity/index.html +++ b/handbook/build/docs/entity/index.html @@ -6,7 +6,7 @@ 9.3 数据库实体 | Fur - + @@ -39,7 +39,7 @@
    // 配置数据库实体
    public void Configure(EntityTypeBuilder<User> entityBuilder, DbContext dbContext, Type dbContextLocator)
    {
    entityBuilder.HasKey(u => u.Id);
    entityBuilder.HasIndex(u => u.Name);
    }
    }
    }

    9.3.3.2 在任何实例类中配置

    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.EntityFrameworkCore.Metadata.Builders;
    using System;
    namespace Fur.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 数据库实体。

    9.3.4 数据库实体配置说明

    Fur 框架会自动扫描所有继承 IEntity 接口的类进行 DbSet<TEntity> 注册,也就是实现自动配置 DbContextOnModelCreating

    如果需要跳过自动注册,只需要贴 [NonAutomatic][NonBeScan] 特性即可。一旦贴了次特性,那么就需要手动配置 DbContextOnModelCreating

    9.3.5 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/event-bus/index.html b/handbook/build/docs/event-bus/index.html index baa9d65e2a0..75ab9e11505 100644 --- a/handbook/build/docs/event-bus/index.html +++ b/handbook/build/docs/event-bus/index.html @@ -6,7 +6,7 @@ 18. 事件总线 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/handbook/build/docs/friendly-exception/index.html b/handbook/build/docs/friendly-exception/index.html index 8b9a955d4b6..fa758db9f41 100644 --- a/handbook/build/docs/friendly-exception/index.html +++ b/handbook/build/docs/friendly-exception/index.html @@ -6,7 +6,7 @@ 7. 友好异常处理 | Fur - + @@ -59,7 +59,7 @@
    namespace Fur.Application
    {
    public class FurAppService : IDynamicApiController
    {
    [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 异常模型提供器

    文档整理中...

    7.14 Fur 内置异常

    • EFCoreErrorCodesEF Core 操作异常
      • DataNotFound:未找到数据
      • KeyNotSet:没有设置主键

    7.15 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/get-start/index.html b/handbook/build/docs/get-start/index.html index 9fe38070c3e..261cc161b27 100644 --- a/handbook/build/docs/get-start/index.html +++ b/handbook/build/docs/get-start/index.html @@ -6,7 +6,7 @@ 2. 一分钟入门 | Fur - + @@ -20,7 +20,7 @@ - +
    @@ -30,8 +30,8 @@
    /// <summary>
    /// 姓名
    /// </summary>
    [MaxLength(32)]
    public string Name { get; set; }
    /// <summary>
    /// 年龄
    /// </summary>
    public int Age { get; set; }
    /// <summary>
    /// 住址
    /// </summary>
    public string Address { get; set; }
    }
    }

    2.2.2 创建数据库上下文

    Fur.EntityFramework.Core 中添加 FurDbContext 数据库上下文,代码如下:

    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    -
    namespace Fur.EntityFramework.Core
    {
    [AppDbContext("DbConnectionString")] // 配置连接字符串
    public class FurDbContext : AppDbContext<FurDbContext> // 继承 AppDbContext<> 类
    {
    /// <summary>
    /// 继承父类构造函数
    /// </summary>
    /// <param name="options"></param>
    public FurDbContext(DbContextOptions<FurDbContext> options) : base(options)
    {
    }
    }
    }

    2.2.3 配置数据库连接字符串

    Fur.EntityFramework.Coredbsettings.json 中配置数据库连接字符串,代码如下:

    Fur\framework\Fur.EntityFramework.Core\dbsettings.json
    {
    "ConnectionStrings": {
    "DbConnectionString": "Server=localhost;Database=Fur;User=sa;Password=000000;MultipleActiveResultSets=True;",
    "Sqlite3ConnectionString": "Data Source=./Fur.db"
    }
    }

    2.2.4 配置数据库上下文

    Fur.EntityFramework.CoreFurEntityFrameworkCoreStartup 中配置数据库上下文,代码如下:

    Fur\framework\Fur.EntityFramework.Core\FurEntityFrameworkCoreStartup.cs
    using Fur.DatabaseAccessor;
    using Microsoft.Extensions.DependencyInjection;
    -
    namespace Fur.EntityFramework.Core
    {
    [Startup(600)]
    public sealed class FurEntityFrameworkCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    // 配置数据库上下文,支持N个数据库
    services.AddDatabaseAccessor(options =>
    {
    options.AddDbPool<FurDbContext>(DbProvider.Sqlite);
    });
    }
    }
    }
    特别说明

    Fur 演示示例中,默认已经在 Fur.EntityFramework.Core 层安装了 Microsoft.EntityFrameworkCore.Sqlite 包。

    如果你需要安装对应的数据库版本,可以查阅 【9.18 多数据库操作】 章节。

    2.2.5 通过命令创建数据库表

    打开 程序包管理控制台,如下图所示:

    选择 默认项目为Fur.Database.Migrations,如下图所示:

    输入以下命令

    Add-Migration v0.0.1

    提交到数据库更改

    Update-Database

    2.3 增删查改分页例子

    using Fur.Core;
    using Fur.DatabaseAccessor;
    using Fur.DynamicApiController;
    using Mapster;
    using Microsoft.EntityFrameworkCore;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    +
    namespace Fur.EntityFramework.Core
    {
    [AppDbContext("Data Source=./Fur.db")] // 配置连接字符串
    public class FurDbContext : AppDbContext<FurDbContext> // 继承 AppDbContext<> 类
    {
    /// <summary>
    /// 继承父类构造函数
    /// </summary>
    /// <param name="options"></param>
    public FurDbContext(DbContextOptions<FurDbContext> options) : base(options)
    {
    }
    }
    }

    2.2.3 配置数据库上下文

    Fur.EntityFramework.CoreFurEntityFrameworkCoreStartup 中配置数据库上下文,代码如下:

    Fur\framework\Fur.EntityFramework.Core\FurEntityFrameworkCoreStartup.cs
    using Fur.DatabaseAccessor;
    using Microsoft.Extensions.DependencyInjection;
    +
    namespace Fur.EntityFramework.Core
    {
    [AppStartup(600)]
    public sealed class FurEntityFrameworkCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddDatabaseAccessor(options =>
    {
    options.AddDbPool<FurDbContext>(DbProvider.Sqlite);
    });
    }
    }
    }
    特别说明

    Fur 演示示例中,默认已经在 Fur.EntityFramework.Core 层安装了 Microsoft.EntityFrameworkCore.Sqlite 包。

    如果你需要安装对应的数据库版本,可以查阅 【9.18 多数据库操作】 章节。

    2.2.4 通过命令创建数据库表

    打开 程序包管理控制台,如下图所示:

    选择 默认项目为Fur.Database.Migrations,如下图所示:

    输入以下命令

    Add-Migration v0.0.1

    提交到数据库更改

    Update-Database

    2.3 增删查改分页例子

    using Fur.Core;
    using Fur.DatabaseAccessor;
    using Fur.DynamicApiController;
    using Mapster;
    using Microsoft.EntityFrameworkCore;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    namespace Fur.Application
    {
    [DynamicApiController] // 这里使用特性方式
    public class FurService /*: IDynamicApiController*/ // 也可以使用接口方式
    {
    // 初始化仓储
    private readonly IRepository<Person> _personRepository;
    public FurService(IRepository<Person> personRepository)
    {
    _personRepository = personRepository;
    }
    /// <summary>
    /// 新增一条
    /// </summary>
    public async Task<int> Insert(PersonDto personDto)
    {
    // 如果不需要返回自增Id,使用 InsertAsync即可
    var newEntity = await _personRepository.InsertNowAsync(personDto.Adapt<Person>());
    return newEntity.Entity.Id;
    // 还可以直接操作
    // await personDto.Adapt<Person>().InsertNowAsync();
    }
    @@ -43,9 +43,9 @@
    /// <summary>
    /// 分页查询
    /// </summary>
    /// <param name="pageIndex"></param>
    /// <param name="pageSize"></param>
    /// <returns></returns>
    public async Task<PagedList<PersonDto>> GetAllByPage(int pageIndex = 1, int pageSize = 10)
    {
    var pageResult = await _personRepository.AsQueryable().ToPagedListAsync(pageIndex, pageSize);
    return pageResult.Adapt<PagedList<PersonDto>>();
    }
    }
    }

    附上 PersonDto

    using System.ComponentModel.DataAnnotations;
    namespace Fur.Application
    {
    public class PersonDto
    {
    /// <summary>
    /// Id
    /// </summary>
    public int? Id { get; set; }
    /// <summary>
    /// 姓名
    /// </summary>
    [StringLength(32, MinimumLength = 2)]
    public string Name { get; set; }
    -
    /// <summary>
    /// 年龄
    /// </summary>
    public int Age { get; set; }
    }
    }

    说好一分钟入门,你们用了多长时间。😁

    +
    /// <summary>
    /// 年龄
    /// </summary>
    public int Age { get; set; }
    }
    }

    说好一分钟入门,你们用了多长时间。😁

    - + @@ -59,6 +59,6 @@ - + \ No newline at end of file diff --git a/handbook/build/docs/grpc/index.html b/handbook/build/docs/grpc/index.html index f2cf1e5aa95..d5476840fc4 100644 --- a/handbook/build/docs/grpc/index.html +++ b/handbook/build/docs/grpc/index.html @@ -6,7 +6,7 @@ 24. Grpc 服务 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/handbook/build/docs/index.html b/handbook/build/docs/index.html index f86efc37868..bc1b4f8d261 100644 --- a/handbook/build/docs/index.html +++ b/handbook/build/docs/index.html @@ -6,7 +6,7 @@ 1.1 介绍 | Fur - + @@ -26,7 +26,7 @@

    1.1 介绍

    star fork GitHub stars GitHub forks GitHub license

    Fur.NET 5 平台下极易入门、极速开发的 Web 应用框架。

    🍕 名字的由来

    故事是这样子的:

    起初,想开发一个极易入门、极易维护的框架,开发理念为:一切从简,只为了更懒

    所以自然而然想到了:Lazier,也就是 更懒 的意思。但是 更懒更烂 读音相近且中文名没有特色,对此换名问题我苦恼了好几天。

    刚好有一次我在博客园中帮一个博友解答问题,解决后博友赞扬我对 .NET Core 颇有了解,我就顺嘴回答了一句:“略懂皮毛”

    就这时,脑瓜子灵机一动,干脆起名为:“皮毛”?英文单词 Fur [fɜː(r)]”,单词又短而且中文读音既俗气又顺口。😄😎

    所以,Fur 就诞生了。

    之后就有了 “小僧不才,略懂皮毛(Fur)。” 广告语 和 chinadot.net 域名。

    🍔 关于 LOGO

    Fur LOGO 设计由 F U R 三个单词组成:

    我相信很多人看到 Fur 的 LOGO 时都会问:“为什么选择奶牛?”,因为 那些年吹过的牛逼都实现了 🐮

    之所以选择 奶牛 是因为 具有脚踏实地,任劳任怨的做事风格,同时 奶牛 意味着丰富的营养价值,正如 Fur 所能带给你的。

    🍟 文档地址

    https://chinadot.net

    🌭 开源地址

    🍿 Docker 镜像

    docker run --name fur -p 5000:80 monksoul/fur:v1.0.0-2020.10.07

    🥞 架构设计

    正在整理中...

    🥝 功能模块

    🥐 框架依赖

    Fur 为了追求极速入门,极致性能,尽可能的不使用或减少第三方依赖。目前 Fur 仅集成了以下三个依赖:

    麻雀虽小五脏俱全。Fur 即使只集成了这三个依赖,但是主流的 依赖注入/控制反转AOP 面向切面编程,事件总线数据验证数据库操作 等等一个都不少。

    🥗 环境要求

    • Visual Studio 2019 Preview 16.8 +
    • .NET 5 SDK +
    • .Net Standard 2.1 +

    🥪 支持平台

    • 运行环境
      • Windows
      • Linux
      • MacOS
      • Docker/K8S/K3S/Rancher
    • 数据库
      • SqlServer
      • Sqlite
      • Azure Cosmos
      • MySql
      • PostgreSQL
      • InMemoryDatabase
      • Oracle
      • Firebird
      • 达梦数据库
    • 应用部署
      • Kestrel
      • Nginx
      • Jexus
      • IIS
      • Apache
      • PM2
      • Supervisor
      • 单文件
      • 容器(Docker/K8S/K3S/Rancher)

    🍖 关于性能

    Fur 目前采用 Visual Studio 2019 Preview 16.8 自带性能测试和 JMeter 进行测试,由于篇幅有限,只贴部分测试图,测试结果如下:


    🍚 关于作者

    一个拥有 12 年开发经验 .NETer。喜欢分享,喜欢新技术,在互联网多个技术领域皆有涉猎。

    🍤 项目成员

    🎈 欢迎更多的开发者加入 Fur 大家庭。

    🍝 谁在使用

    • 百签科技(广东)有限公司
    • 码为科技(广州)有限公司
    • 广州启顺国际货运代理有限公司
    • 森丰供应链服务(广州)有限公司
    • 中山赢友网络科技有限公司
    • 中山模思软件科技有限公司
    • 珠海市恒泰新软件有限责任公司
    • 珠海思诺锐创软件有限公司
    • 深圳市易胜科技有限公司
    • 重庆虫儿飞科技有限公司
    • 重庆林木森科技有限公司

    如果您的项目使用到 Fur 开发,可以告诉我们。

    🍻 贡献代码

    Fur 遵循 Apache-2.0 开源协议,欢迎大家提交 PRIssue

    如果要为项目做出贡献,请查看贡献指南。

    🍍 捐赠列表

    注:排序按捐赠顺序书写

    捐赠人昵称捐赠金额(元)附语
    🤴 爱吃油麦菜100感谢您的开源项目!
    👳‍♂️ 麦壳饼200感谢您的开源项目!
    👨 Sun100感谢您的开源项目!
    👶 d61761720感谢您的开源项目!
    👦 Diqiguoji00816.66见贤思齐
    👲 nodyang100感谢您的开源项目!
    👳‍♀️ mictxd100吹过的牛都实现。
    🧓 欧流全10希望将来超越 Spring
    👨‍⚕️ lionkon10...看了框架感觉拿来学习是很不错的...

    非常感谢您们的支持,正是因为您们,中国开源才可以越走越远,Fur 越走越远。

    🥔 QQ 交流群

    🧆 友情链接

    👉 Fur 👉 SqlSugar 👉 Layx 👉 t-io

    - + diff --git a/handbook/build/docs/job/index.html b/handbook/build/docs/job/index.html index 39b800d19b6..77e849a7824 100644 --- a/handbook/build/docs/job/index.html +++ b/handbook/build/docs/job/index.html @@ -6,7 +6,7 @@ 22. 任务调度 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/handbook/build/docs/local-language/index.html b/handbook/build/docs/local-language/index.html index a31801b7695..5721e5ab7bf 100644 --- a/handbook/build/docs/local-language/index.html +++ b/handbook/build/docs/local-language/index.html @@ -6,7 +6,7 @@ 16. 多语言处理 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/handbook/build/docs/logging/index.html b/handbook/build/docs/logging/index.html index 8615f828a7a..18ab4b2fb41 100644 --- a/handbook/build/docs/logging/index.html +++ b/handbook/build/docs/logging/index.html @@ -6,7 +6,7 @@ 19. 日志记录 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/handbook/build/docs/object-mapper/index.html b/handbook/build/docs/object-mapper/index.html index 4522477d0ef..4edb829fbdb 100644 --- a/handbook/build/docs/object-mapper/index.html +++ b/handbook/build/docs/object-mapper/index.html @@ -6,7 +6,7 @@ 12. 对象数据映射 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/handbook/build/docs/options/index.html b/handbook/build/docs/options/index.html index 181d23baa26..fc0982e6b1f 100644 --- a/handbook/build/docs/options/index.html +++ b/handbook/build/docs/options/index.html @@ -6,7 +6,7 @@ 4.2 选项 | Fur - + @@ -41,7 +41,7 @@
    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.9 选项的优缺点

    优点

    • 强类型配置
    • 提供多种读取方式
    • 支持热加载
    • 支持设置默认值/后期配置
    • 支持在运行环境中动态配置
    • 支持验证配置有效性
    • 支持更改通知
    • 支持命名选项

    缺点

    • 需要定义对应类型
    • 需要在启动时注册

    4.2.10 反馈与建议

    与我们交流

    给 Fur 提 Issue


    了解更多

    想了解更多 选项 知识可查阅 ASP.NET Core - 选项 章节。

    - + diff --git a/handbook/build/docs/performance/index.html b/handbook/build/docs/performance/index.html index 47fbbddb7c6..e2e56adc8bb 100644 --- a/handbook/build/docs/performance/index.html +++ b/handbook/build/docs/performance/index.html @@ -6,7 +6,7 @@ 27.2 性能测试 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/handbook/build/docs/process-service/index.html b/handbook/build/docs/process-service/index.html index 9c95f5317cc..22bdde118f6 100644 --- a/handbook/build/docs/process-service/index.html +++ b/handbook/build/docs/process-service/index.html @@ -6,7 +6,7 @@ 21. 进程服务 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/handbook/build/docs/saas/index.html b/handbook/build/docs/saas/index.html index 907cd7d4d85..61737f0c31c 100644 --- a/handbook/build/docs/saas/index.html +++ b/handbook/build/docs/saas/index.html @@ -6,7 +6,7 @@ 10. SaaS 多租户 | Fur - + @@ -20,7 +20,7 @@ - +
    @@ -32,7 +32,7 @@ 三种方案比较,第三种方案的维护和购置成本最低,允许每个数据库支持的租户数量最多。

  • 缺点: 隔离级别最低,安全性最低,需要在设计开发时加大对安全的开发量; 数据备份和恢复最困难,需要逐表逐条备份和还原。

  • 10.4 多租户使用方案

    Fur 框架支持以上三种多租户实现方案,使用简单且容易维护。下面分别使用三种不同方式演示多租户方案用法。

    10.5 基于 TenantId 的方式

    此方式在中小型企业系统中最为常用,维护成本低,购置成本低。

    10.5.1 创建租户数据库上下文

    Fur.EntityFramework.Core\DbContexts\MultiTenantDbContext.cs
    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    namespace Fur.EntityFramework.Core
    {
    [AppDbContext("Sqlite3ConnectionString")]
    public class MultiTenantDbContext : AppDbContext<MultiTenantDbContext, MultiTenantDbContextLocator>
    {
    public MultiTenantDbContext(DbContextOptions<MultiTenantDbContext> options) : base(options)
    {
    }
    }
    }
    特别注意

    多租户操作建议单独一个数据库上下文,而且需指定 MultiTenantDbContextLocator 数据库上下文定位器。

    10.5.2 注册多租户数据库上下文

    using Fur.DatabaseAccessor;
    using Microsoft.Extensions.DependencyInjection;
    -
    namespace Fur.EntityFramework.Core
    {
    [Startup(600)]
    public sealed class FurEntityFrameworkCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddDatabaseAccessor(options =>
    {
    options.AddDbPool<FurDbContext>(DbProvider.Sqlite);
    options.AddDbPool<MultiTenantDbContext, MultiTenantDbContextLocator>(DbProvider.Sqlite);
    });
    }
    }
    }

    10.5.3 添加 Tenant 种子数据

    Fur.EntityFramework.Core\SeedDatas\TenantSeedData.cs
    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    using System;
    using System.Collections.Generic;
    +
    namespace Fur.EntityFramework.Core
    {
    [AppStartup(600)]
    public sealed class FurEntityFrameworkCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddDatabaseAccessor(options =>
    {
    options.AddDbPool<FurDbContext>(DbProvider.Sqlite);
    options.AddDbPool<MultiTenantDbContext, MultiTenantDbContextLocator>(DbProvider.Sqlite);
    });
    }
    }
    }

    10.5.3 添加 Tenant 种子数据

    Fur.EntityFramework.Core\SeedDatas\TenantSeedData.cs
    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    using System;
    using System.Collections.Generic;
    namespace Fur.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 无需配置种子数据。

    10.5.4 根据模型创建 Tenant

    Add-Migration add_tenant_table -Context MultiTenantDbContext
    Update-Database -Context MultiTenantDbContext

    10.5.5 实现 IMultiTenantOnTable 接口

    在需要多租户的数据库上下文中实现 IMultiTenantOnTable 接口,如:

    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    using System;
    namespace Fur.EntityFramework.Core
    {
    [AppDbContext("Sqlite3ConnectionString")]
    public class FurDbContext : AppDbContext<FurDbContext>, IMultiTenantOnTable, IModelBuilderFilter
    {
    public FurDbContext(DbContextOptions<FurDbContext> options) : base(options)
    {
    }
    public Guid? GetTenantId()
    {
    return base.Tenant.TenantId;
    }
    }
    }

    GetTenantId() 方法中,首先获取请求的 主机地址,然后根据主机地址查询对应的租户 TenantIdId,避免多次查询数据库,这里使用了 IMemoryCache 内存缓存。

    10.5.6 实现 IModelBuilderFilter 接口

    IModelBuilderFilter 接口是全局查询过滤器实现接口,所以我们需要配置实体 TenantId 过滤器

    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.EntityFrameworkCore.Metadata.Builders;
    using System;
    @@ -46,7 +46,7 @@
    // 获取所有新增和更新的实体
    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 = base.TenantId;
    break;
    // 排除租户Id
    case EntityState.Modified:
    entity.Property(nameof(Entity.TenantId)).IsModified = false;
    break;
    }
    }
    }
    }
    }

    10.6 基于 Database 的方式

    此方式在中大型企业系统中最为常用,一个租户(客户)一个独立的数据库。

    10.6.1 创建租户数据库上下文

    Fur.EntityFramework.Core\DbContexts\MultiTenantDbContext.cs
    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    namespace Fur.EntityFramework.Core
    {
    [AppDbContext("Sqlite3ConnectionString")]
    public class MultiTenantDbContext : AppDbContext<MultiTenantDbContext, MultiTenantDbContextLocator>
    {
    public MultiTenantDbContext(DbContextOptions<MultiTenantDbContext> options) : base(options)
    {
    }
    }
    }
    特别注意

    多租户操作建议单独一个数据库上下文,而且需指定 MultiTenantDbContextLocator 数据库上下文定位器。

    10.6.2 注册多租户数据库上下文

    using Fur.DatabaseAccessor;
    using Microsoft.Extensions.DependencyInjection;
    -
    namespace Fur.EntityFramework.Core
    {
    [Startup(600)]
    public sealed class FurEntityFrameworkCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddDatabaseAccessor(options =>
    {
    options.AddDb<FurDbContext>(DbProvider.Sqlite);
    options.AddDbPool<MultiTenantDbContext, MultiTenantDbContextLocator>(DbProvider.Sqlite);
    });
    }
    }
    }
    特别注意

    需要 Database 多租户方案的数据库上下文需要采用 AddDb 注册,而不是 AddDbPool。原因是 AddDbPool 方式注册后续不支持 OnConfiguring 重写!!!

    10.6.3 添加 Tenant 种子数据

    Fur.EntityFramework.Core\SeedDatas\TenantSeedData.cs
    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    using System;
    using System.Collections.Generic;
    +
    namespace Fur.EntityFramework.Core
    {
    [AppStartup(600)]
    public sealed class FurEntityFrameworkCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddDatabaseAccessor(options =>
    {
    options.AddDb<FurDbContext>(DbProvider.Sqlite);
    options.AddDbPool<MultiTenantDbContext, MultiTenantDbContextLocator>(DbProvider.Sqlite);
    });
    }
    }
    }
    特别注意

    需要 Database 多租户方案的数据库上下文需要采用 AddDb 注册,而不是 AddDbPool。原因是 AddDbPool 方式注册后续不支持 OnConfiguring 重写!!!

    10.6.3 添加 Tenant 种子数据

    Fur.EntityFramework.Core\SeedDatas\TenantSeedData.cs
    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    using System;
    using System.Collections.Generic;
    namespace Fur.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=./Fur.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 无需配置种子数据。

    10.6.4 根据模型创建 Tenant

    Add-Migration add_tenant_table -Context MultiTenantDbContext
    Update-Database -Context MultiTenantDbContext

    10.6.5 实现 IMultiTenantOnDatabase 接口

    在需要多租户的数据库上下文中实现 IMultiTenantOnDatabase 接口,如:

    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    namespace Fur.EntityFramework.Core
    {
    public class FurDbContext : AppDbContext<FurDbContext>, IMultiTenantOnDatabase
    {
    public FurDbContext(DbContextOptions<FurDbContext> options) : base(options)
    {
    }
    public string GetDatabaseConnectionString()
    {
    return base.Tenant.ConnectionString;
    }
    }
    }

    10.6.6 重写 OnConfiguring 方法

    在需要多租户的数据库上下文中重写 OnConfiguring 方法并配置连接字符串:

    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    @@ -55,12 +55,12 @@
    base.OnConfiguring(optionsBuilder);
    }
    public string GetDatabaseConnectionString()
    {
    return base.Tenant.ConnectionString;
    }
    }
    }

    10.7 基于 Schema 的方式

    此方式在中小型企业系统中也不少见,一个租户(客户)共享数据库且不同 Schema

    10.7.1 创建租户数据库上下文

    Fur.EntityFramework.Core\DbContexts\MultiTenantDbContext.cs
    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    namespace Fur.EntityFramework.Core
    {
    [AppDbContext("Sqlite3ConnectionString")]
    public class MultiTenantDbContext : AppDbContext<MultiTenantDbContext, MultiTenantDbContextLocator>
    {
    public MultiTenantDbContext(DbContextOptions<MultiTenantDbContext> options) : base(options)
    {
    }
    }
    }
    特别注意

    多租户操作建议单独一个数据库上下文,而且需指定 MultiTenantDbContextLocator 数据库上下文定位器。

    10.7.2 注册多租户数据库上下文

    using Fur.DatabaseAccessor;
    using Microsoft.Extensions.DependencyInjection;
    -
    namespace Fur.EntityFramework.Core
    {
    [Startup(600)]
    public sealed class FurEntityFrameworkCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddDatabaseAccessor(options =>
    {
    options.AddDbPool<FurDbContext>(DbProvider.Sqlite);
    options.AddDbPool<MultiTenantDbContext, MultiTenantDbContextLocator>(DbProvider.Sqlite);
    });
    }
    }
    }

    10.7.3 添加 Tenant 种子数据

    Fur.EntityFramework.Core\SeedDatas\TenantSeedData.cs
    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    using System;
    using System.Collections.Generic;
    +
    namespace Fur.EntityFramework.Core
    {
    [AppStartup(600)]
    public sealed class FurEntityFrameworkCoreStartup : AppStartup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddDatabaseAccessor(options =>
    {
    options.AddDbPool<FurDbContext>(DbProvider.Sqlite);
    options.AddDbPool<MultiTenantDbContext, MultiTenantDbContextLocator>(DbProvider.Sqlite);
    });
    }
    }
    }

    10.7.3 添加 Tenant 种子数据

    Fur.EntityFramework.Core\SeedDatas\TenantSeedData.cs
    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    using System;
    using System.Collections.Generic;
    namespace Fur.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="fur" // Schema
    }
    };
    }
    }
    }
    特别说明

    该步骤只在 Code First 方式执行,Database First 无需配置种子数据。

    10.7.4 根据模型创建 Tenant

    Add-Migration add_tenant_table -Context MultiTenantDbContext
    Update-Database -Context MultiTenantDbContext

    10.7.5 实现 IMultiTenantOnSchema 接口

    在需要多租户的数据库上下文中实现 IMultiTenantOnSchema 接口,如:

    using Fur.DatabaseAccessor;
    using Microsoft.EntityFrameworkCore;
    namespace Fur.EntityFramework.Core
    {
    [AppDbContext("Sqlite3ConnectionString")]
    public class FurDbContext : AppDbContext<FurDbContext>, IMultiTenantOnSchema
    {
    public FurDbContext(DbContextOptions<FurDbContext> options) : base(options)
    {
    }
    public string GetSchemaName()
    {
    return base.Tenant.Schema;
    }
    }
    }

    10.7.6 关于 Code First 数据迁移

    基于 Schema 方式比较特别,生成数据迁移的时候没办法获取租户信息,所以建议分开多次迁移,如:

    public string GetSchemaName()
    {
    return base.Tenant.Schema?? "租户一Schema";
    }
    public string GetSchemaName()
    {
    return base.Tenant.Schema?? "租户二Schema";
    }

    这样就可以在迁移的时候生成多次迁移了。

    10.8 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + @@ -74,6 +74,6 @@ - + \ No newline at end of file diff --git a/handbook/build/docs/signalr/index.html b/handbook/build/docs/signalr/index.html index bca79a83d51..7e940afe959 100644 --- a/handbook/build/docs/signalr/index.html +++ b/handbook/build/docs/signalr/index.html @@ -6,7 +6,7 @@ 23. 即时通讯 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/handbook/build/docs/source/index.html b/handbook/build/docs/source/index.html index 738cfd31d3d..3a7b729ff5e 100644 --- a/handbook/build/docs/source/index.html +++ b/handbook/build/docs/source/index.html @@ -6,7 +6,7 @@ 1.2 源码结构 | Fur - + @@ -58,7 +58,7 @@
    #prefer fields not to be prefaced with this. or Me. in Visual Basic
    dotnet_style_qualification_for_field = false:suggestion
    #prefer methods not to be prefaced with this. or Me. in Visual Basic
    dotnet_style_qualification_for_method = false:suggestion
    #prefer properties not to be prefaced with this. or Me. in Visual Basic
    dotnet_style_qualification_for_property = false:suggestion
    # Add file header
    file_header_template = -----------------------------------------------------------------------------\nFur 是 .NET 5 平台下极易入门、极速开发的 Web 应用框架。\nCopyright © 2020 Fur, Baiqian Co.,Ltd.\n\n框架名称:Fur\n框架作者:百小僧\n框架版本:1.0.0\n源码地址:Gitee:https://gitee.com/monksoul/Fur \n Github:https://github.com/monksoul/Fur \n开源协议:Apache-2.0(http://www.apache.org/licenses/LICENSE-2.0)\n-----------------------------------------------------------------------------

    1.2.4 Fur 核心层

    Fur 核心层是 Fur 框架的中心,也是 Fur 能够支撑起来的必备层。

    源码结构:

    Fur
    ├─Fur.csproj
    ├─Fur.csproj.user
    ├─FurStartup.cs
    ├─ViewEngine
    | ├─IViewEngine.cs
    | ├─ViewEngine.cs
    | ├─Templates
    | | ├─IViewEngineCompiledTemplate.cs
    | | ├─IViewEngineTemplate.cs
    | | ├─ViewEngineCompiledTemplate.cs
    | | └ViewEngineTemplate.cs
    | ├─Options
    | | └ViewEngineCompilationOptions.cs
    | ├─Models
    | | └AnonymousTypeWrapper.cs
    | ├─Exceptions
    | | ├─ViewEngineCompilationException.cs
    | | └ViewEngineException.cs
    | ├─Compilations
    | | ├─IViewEngineCompilationOptionsBuilder.cs
    | | └ViewEngineCompilationOptionsBuilder.cs
    ├─UnifyResult
    | ├─Providers
    | | ├─IUnifyResultProvider.cs
    | | └RESTfulResultProvider.cs
    | ├─Models
    | | └RESTfulResult.cs
    | ├─Filters
    | | └SuccessUnifyResultFilter.cs
    | ├─Extensions
    | | └UnifyResultServiceCollectionExtensions.cs
    ├─SpecificationDocument
    | ├─Options
    | | └SpecificationDocumentSettingsOptions.cs
    | ├─Models
    | | ├─GroupOrder.cs
    | | ├─SpecificationOpenApiInfo.cs
    | | ├─SpecificationOpenApiSecurityRequirementItem.cs
    | | └SpecificationOpenApiSecurityScheme.cs
    | ├─Extensions
    | | ├─SpecificationDocumentApplicationBuilderExtensions.cs
    | | └SpecificationDocumentServiceCollectionExtensions.cs
    | ├─Builders
    | | └SpecificationDocumentBuilder.cs
    | ├─Assets
    | | └index-mini-profiler.html
    ├─ObjectMapper
    | ├─Extensions
    | | └ObjectMapperServiceCollectionExtensions.cs
    | ├─Dependencies
    | | └IObjectMapper.cs
    ├─LinqBuilder
    | ├─Visitors
    | | └ParameterReplaceExpressionVisitor.cs
    | ├─Extensions
    | | └LinqExtensions.cs
    | ├─Builders
    | | └LinqExpression.cs
    ├─FriendlyException
    | ├─Oops.cs
    | ├─Providers
    | | └IErrorCodeTypeProvider.cs
    | ├─Options
    | | └ErrorCodeMessageSettingsOptions.cs
    | ├─Models
    | | └MethodIfException.cs
    | ├─Filters
    | | └FriendlyExceptionFilter.cs
    | ├─Extensions
    | | └FriendlyExceptionServiceCollectionExtensions.cs
    | ├─Attributes
    | | ├─ErrorCodeItemMetadataAttribute.cs
    | | ├─ErrorCodeTypeAttribute.cs
    | | └IfExceptionAttribute.cs
    ├─DynamicApiController
    | ├─Penetrates.cs
    | ├─Providers
    | | └DynamicApiControllerFeatureProvider.cs
    | ├─Options
    | | └DynamicApiControllerSettingsOptions.cs
    | ├─Models
    | | └ParameterRouteTemplate.cs
    | ├─Extensions
    | | └DynamicApiControllerServiceCollectionExtensions.cs
    | ├─Enums
    | | └ApiSeats.cs
    | ├─Dependencies
    | | └IDynamicApiController.cs
    | ├─Conventions
    | | └DynamicApiControllerApplicationModelConvention.cs
    | ├─Attributes
    | | ├─ApiDescriptionSettingsAttribute.cs
    | | ├─ApiSeatAttribute.cs
    | | └DynamicApiControllerAttribute.cs
    ├─DependencyInjection
    | ├─Extensions
    | | └DependencyInjectionServiceCollectionExtensions.cs
    | ├─Enums
    | | ├─InjectionActions.cs
    | | ├─InjectionPatterns.cs
    | | └RegisterType.cs
    | ├─Dependencies
    | | ├─IDependency.cs
    | | ├─IScoped.cs
    | | ├─ISingleton.cs
    | | ├─ITransient.cs
    | | ├─Aop
    | | | └IDispatchProxy.cs
    | ├─Attributes
    | | ├─InjectionAttribute.cs
    | | └SkipScanAttribute.cs
    ├─DataValidation
    | ├─Validators
    | | └DataValidator.cs
    | ├─Providers
    | | └IValidationMessageTypeProvider.cs
    | ├─Options
    | | └ValidationTypeMessageSettingsOptions.cs
    | ├─Models
    | | └DataValidationResult.cs
    | ├─Filters
    | | └DataValidationFilter.cs
    | ├─Extensions
    | | ├─DataValidationExtensions.cs
    | | └DataValidationServiceCollectionExtensions.cs
    | ├─Enums
    | | ├─ValidationPattern.cs
    | | └ValidationTypes.cs
    | ├─Attributes
    | | ├─DataValidationAttribute.cs
    | | ├─NonValidationAttribute.cs
    | | ├─ValidationItemMetadataAttribute.cs
    | | ├─ValidationMessageAttribute.cs
    | | ├─ValidationMessageTypeAttribute.cs
    | | └ValidationTypeAttribute.cs
    ├─DataEncryption
    | ├─AESEncryption.cs
    | ├─DESCEncryption.cs
    | └MD5Encryption.cs
    ├─DatabaseAccessor
    | ├─UnitOfWork
    | | ├─Filters
    | | | └UnitOfWorkFilter.cs
    | | ├─Attributes
    | | | ├─NonTransactAttribute.cs
    | | | └UnitOfWorkAttribute.cs
    | ├─Repositories
    | | ├─EFCoreRepository.cs
    | | ├─IMSRepository.cs
    | | ├─IRepository.cs
    | | ├─ISqlRepository.cs
    | | ├─MSRepository.cs
    | | ├─SqlRepository.cs
    | | ├─Implantations
    | | | ├─DeletableRepository.cs
    | | | ├─InsertableRepository.cs
    | | | ├─OperableRepository.cs
    | | | ├─ReadableRepository.cs
    | | | ├─SqlExecutableRepository.cs
    | | | ├─SqlReaderRepository.cs
    | | | ├─UpdateableRepository.cs
    | | | └WritableRepository.cs
    | | ├─Dependencies
    | | | ├─IDeletableRepository.cs
    | | | ├─IInsertableRepository.cs
    | | | ├─IOperableRepository.cs
    | | | ├─IReadableRepository.cs
    | | | ├─IRepositoryDependency.cs
    | | | ├─ISqlExecutableRepository.cs
    | | | ├─ISqlReaderRepository.cs
    | | | ├─IUpdateableRepository.cs
    | | | └IWritableRepository.cs
    | ├─Pools
    | | ├─DbContextPool.cs
    | | └IDbContextPool.cs
    | ├─Options
    | | └DatabaseAccessorSettingsOptions.cs
    | ├─MultiTenants
    | | ├─Providers
    | | | ├─IMultiTenantOnDatabaseProvider.cs
    | | | ├─IMultiTenantOnSchemaProvider.cs
    | | | ├─IMultiTenantOnTableProvider.cs
    | | | └IMultiTenantProviderDependency.cs
    | | ├─Locators
    | | | └MultiTenantDbContextLocator.cs
    | | ├─Enums
    | | | └MultiTenantOptions.cs
    | | ├─Entities
    | | | └Tenant.cs
    | ├─Models
    | | ├─DbProvider.cs
    | | ├─PagedList.cs
    | | ├─ProcedureOutputResult.cs
    | | └ProcedureOutputValue.cs
    | ├─Locators
    | | ├─IDbContextLocator.cs
    | | └MasterDbContextLocator.cs
    | ├─Interceptors
    | | ├─DbContextSaveChangesInterceptor.cs
    | | ├─SqlCommandProfilerInterceptor.cs
    | | └SqlConnectionProfilerInterceptor.cs
    | ├─Helpers
    | | └DbHelpers.cs
    | ├─Extensions
    | | ├─DatabaseAccessorServiceCollectionExtensions.cs
    | | ├─PagedQueryableExtensions.cs
    | | ├─Repositories
    | | | ├─IEntityDbContextLocatorExtensions.cs
    | | | ├─IEntityExtensions.cs
    | | | └SqlExtensions.cs
    | | ├─DatabaseProvider
    | | | ├─DatabaseProviderServiceCollectionExtensions.cs
    | | | └Penetrates.cs
    | | ├─DatabaseFacade
    | | | ├─DbDataConvertExtensions.cs
    | | | ├─DbObjectExtensions.cs
    | | | └SqlAdoNetExtensions.cs
    | ├─Enums
    | | ├─DbFunctionType.cs
    | | ├─EFCoreErrorCodes.cs
    | | └ManualOptions.cs
    | ├─Entities
    | | ├─Dependencies
    | | | ├─Entity.cs
    | | | ├─EntityBase.cs
    | | | ├─EntityNotKey.cs
    | | | ├─IEntity.cs
    | | | └IEntityNotKey.cs
    | | ├─Configures
    | | | ├─IEntitySeedData.cs
    | | | ├─IEntityTypeBuilder.cs
    | | | ├─IModelBuilderDependency.cs
    | | | └IModelBuilderFilter.cs
    | | ├─Attributes
    | | | ├─FakeDeleteAttribute.cs
    | | | ├─NonAutomaticAttribute.cs
    | | | └QueryableFunctionAttribute.cs
    | ├─DynamicModels
    | | ├─DynamicModelCacheKeyFactory.cs
    | | └IEntityMutableTable.cs
    | ├─Contexts
    | | ├─AppDbContext.cs
    | | ├─Builders
    | | | ├─AppDbContextBuilder.cs
    | | | ├─Models
    | | | | └DbContextCorrelationType.cs
    | | ├─Attributes
    | | | └DbContextAttribute.cs
    | ├─Attributes
    | | └DbParameterAttribute.cs
    | ├─Advances
    | | ├─Proxies
    | | | └SqlDispatchProxy.cs
    | | ├─Models
    | | | └SqlProxyMethod.cs
    | | ├─Dependencies
    | | | └ISqlDispatchProxy.cs
    | | ├─Attributes
    | | | ├─SqlExecuteAttribute.cs
    | | | ├─SqlFunctionAttribute.cs
    | | | ├─SqlProcedureAttribute.cs
    | | | ├─Basics
    | | | | ├─SqlObjectProxyAttribute.cs
    | | | | ├─SqlProxyAttribute.cs
    | | | | └SqlSentenceProxyAttribute.cs
    ├─CorsAccessor
    | ├─Options
    | | └CorsAccessorSettingsOptions.cs
    | ├─Extensions
    | | ├─CorsAccessorApplicationBuilderExtensions.cs
    | | └CorsAccessorServiceCollectionExtensions.cs
    ├─ConfigurableOptions
    | ├─Options
    | | └IConfigurableOptions.cs
    | ├─Extensions
    | | └ConfigurableOptionsServiceCollectionExtensions.cs
    | ├─Attributes
    | | └OptionsSettingsAttribute.cs
    ├─Authorization
    | ├─Penetrates.cs
    | ├─Requirements
    | | └AuthorizePolicyRequirement.cs
    | ├─Providers
    | | └AuthorizePolicyProvider.cs
    | ├─Options
    | | └JWTSettingsOptions.cs
    | ├─Handlers
    | | └AuthorizePolicyHandler.cs
    | ├─Extensions
    | | └PolicyAuthorizationServiceCollectionExtensions.cs
    | ├─Attributes
    | | └AuthorizePolicyAttribute.cs
    ├─App
    | ├─App.cs
    | ├─Startups
    | | ├─AppStartup.cs
    | | └HostingStartup.cs
    | ├─Options
    | | └AppSettingsOptions.cs
    | ├─Filters
    | | └StartupFilter.cs
    | ├─Extensions
    | | ├─AppApplicationBuilderExtensions.cs
    | | ├─AppServiceCollectionExtensions.cs
    | | └ObjectExtensions.cs
    | ├─Attributes
    | | └StartupAttribute.cs

    1.2.5 Fur.Application 业务应用层

    Fur.Application 业务应用层是最常用的层,几乎所有的业务代码都在这个层中编写。

    源码结构:

    Fur.Application
    ├─Fur.Application.Core.csproj
    ├─Fur.Application.Core.xml
    └FurApplicationStartup.cs

    1.2.6 Fur.Core 仓储实体层

    Fur.Core 主要是存储自定义仓储和定义实体的层。

    源码结构:

    Fur.Core
    ├─Fur.Core.csproj
    └FurCoreStartup.cs

    1.2.7 Fur.Database.Migrations 数据库架构维护层

    Fur.Database.Migrations 主要是用来存放 Database FirstCode First 生成的维护文件。

    源码结构:

    Fur.Database.Migrations
    └Fur.Database.Migrations.csproj

    1.2.8 Fur.EntityFramework.Core 数据库上下文配置层

    Fur.EntityFramework.Core 主要是用来配置数据库上下文和其他数据库相关配置信息的。

    源码结构:

    Fur.EntityFramework.Core
    └Fur.EntityFramework.Core.csproj

    1.2.9 Fur.Web.Core 应用核心层

    Fur.Web.Core 主要是用来配置 Web 入口一些代码,如 FilterMiddlewares 等。

    源码结构:

    Fur.Web.Core
    ├─Fur.Web.Core.xml
    └FurWebCoreStartup.cs

    1.2.10 Fur.Web.Entry 应用入口层

    Fur.Web.Entry 是我们的应用层,也就是我们的 Web 项目层,发布层。

    源码结构:

    Fur.Web.Entry
    ├─appsettings.Development.json
    ├─appsettings.json
    ├─Fur.Web.Entry.csproj
    ├─Fur.Web.Entry.csproj.user
    ├─Fur.Web.Entry.xml
    ├─Program.cs
    ├─Startup.cs
    ├─wwwroot
    | └README.md
    ├─Properties
    | └launchSettings.json
    ├─Controllers
    - + diff --git a/handbook/build/docs/specification-document/index.html b/handbook/build/docs/specification-document/index.html index 9c463b91451..a5ca1331745 100644 --- a/handbook/build/docs/specification-document/index.html +++ b/handbook/build/docs/specification-document/index.html @@ -6,7 +6,7 @@ 6. 规范化接口文档 | Fur - + @@ -51,7 +51,7 @@
    "Requirement": {
    "Scheme": {
    "Reference": {
    "Id": "Bearer",
    "Type": "SecurityScheme"
    },
    "Accesses": null
    }
    }
    }
    ]
    }
    }
    }

    6.5.12 在线测试

    如下图所示:

    6.5.13 性能监视 MiniProfiler

    规范化文档默认集成了 MiniProfiler 第三方性能组件,通过该组件可以方便查看请求性能、异常堆栈、数据库操作等信息。默认在 Swagger 首页左上角显示。

    如下图所示:

    小提示

    也可以通过 appsetting.jsonAppSettings:InjectMiniProfiler 设为 false 关闭。

    6.5.14 定义接口输出类型

    using Fur.DynamicApiController;
    using Microsoft.AspNetCore.Mvc;
    namespace Fur.Application
    {
    public class FurAppService : IDynamicApiController
    {
    [ProducesResponseType(201, Type = typeof(TestDto))]
    [ProducesResponseType(400)]
    public string Get()
    {
    return nameof(Fur);
    }
    }
    }

    如下图所示:

    6.6 SpecificationDocumentSettings 配置

    除了上述例子外,Fur 提供了一些配置选项,如:

    • DocumentTitle:文档标题,string,默认 Specification Api Document
    • DefaultGroupName:默认分组名,string,默认 Default
    • EnableAuthorized:是否启用权限控制,bool,默认 true
    • FormatAsV2:采用 Swagger 2.0 版本,bool,默认 false
    • RoutePrefix:规范化文档地址,string,默认 string
    • DocExpansionState:文档显示方式,DocExpansion,默认 List,取值:
      • List:列表式(展开子类),默认值
      • Full:完全展开
      • None:列表式(不展开子类)
    • XmlComments:程序集注释描述文件名(可带 .xmlstring,默认 Fur.Application, Fur.Web.Entry, Fur.Web.Core
    • GroupOpenApiInfos:分组信息配置,SpecificationOpenApiInfo[],默认 { 'Group': 'Default'}
    • SecurityDefinitions:安全策略定义配置,SpecificationOpenApiSecurityScheme[],默认 []

    6.7 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/split-db/index.html b/handbook/build/docs/split-db/index.html index 9ecb27905f9..e2568bb3c7f 100644 --- a/handbook/build/docs/split-db/index.html +++ b/handbook/build/docs/split-db/index.html @@ -6,7 +6,7 @@ 9.27 分表分库 | Fur - + @@ -30,7 +30,7 @@
    // 通过数据库上下文定位器切换
    repository.Change<Entity, MyDbContextLocator2>();

    如需跨库查询,需用到数据库技术,如 SqlServer 链接服务器或同义词。

    • 动态切换数据库表
    // 直接改变表,会有多线程操作bug,同时无法刷新模型
    repository.ChangeTable("数据库表");
    // 创建新的 DbContext,然后刷新 OnModelCreating(推荐方式)
    var dynamicDbContextResolve = App.TransientServices.GetService<Func<Type, IScoped, DbContext>>();
    var dynamicDbContext = dynamicDbContextResolve(typeof(MyDbContextLocator), default);
    // 重新调用 OnModelCreating,在 OnModelCreating 中配置 ToTable("动态表") 即可。
    DynamicModelCacheKeyFactory.RebuildModels();
    var persons= dynamicDbContext.Set<Person>();
    persons.Add(new Person{});
    了解更多

    想了解更多 DynamicModelCacheKeyFactory 知识可查阅 EF Core - 多个模型之间交替 章节。

    9.27.7 反馈与建议

    与我们交流

    给 Fur 提 Issue

    - + diff --git a/handbook/build/docs/tran/index.html b/handbook/build/docs/tran/index.html index 43cc8ec61c3..ae747c56ac1 100644 --- a/handbook/build/docs/tran/index.html +++ b/handbook/build/docs/tran/index.html @@ -6,7 +6,7 @@ 9.25 事务和工作单元 | Fur - + @@ -29,7 +29,7 @@
    var blogs = _testRepository.Entity
    .OrderBy(b => b.Url)
    .ToList();
    // 提交事务
    transaction.Commit();
    }
    catch (Exception)
    {
    // 回滚事务
    transaction.RollBack();
    }
    }

    9.25.4 工作单元特性说明

    9.25.4.1 [UnitOfWork]

    [UnitOfWork] 特性用来标记事务信息,如作用范围,隔离级别等。

    • Enabled:是否启动工作单元,默认 true
    • ScopeOption:定义事务范围行为,默认 TransactionScopeOption.Required
    • IsolationLevel:设置事务隔离级别,默认 IsolationLevel.ReadCommitted;
    • AsyncFlowOption:允许跨线程连续任务的事务流,如有异步操作需开启该选项,默认开启
    特别注意

    一旦方法贴了 [UnitOfWork(false)] 特性后,那么该方法不再启用工作单元模式,也就是不包含事务,也不会自动提交数据库。慎用!

    9.25.4.2 [NonTransact]

    一但方法或类贴了 [NonTransact] 特性,那么将关闭事务操作,但是还是会自动保存数据库到数据。

    9.25.5 常见错误

    • A TransactionScope must be disposed on the same thread that it was created.

    只需要在当前操作方法上贴 [NonTransact] 特性即可。

    9.25.6 反馈与建议

    与我们交流

    给 Fur 提 Issue


    了解更多

    想了解更多 事务 知识可查阅 EF Core - 使用事务 章节。

    - + diff --git a/handbook/build/docs/unittest/index.html b/handbook/build/docs/unittest/index.html index 6087dda81b0..54eeaa0daa3 100644 --- a/handbook/build/docs/unittest/index.html +++ b/handbook/build/docs/unittest/index.html @@ -6,7 +6,7 @@ 27.1 单元测试 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/handbook/build/docs/view-engine/index.html b/handbook/build/docs/view-engine/index.html index d444e767b48..38e27709381 100644 --- a/handbook/build/docs/view-engine/index.html +++ b/handbook/build/docs/view-engine/index.html @@ -6,7 +6,7 @@ 17. 视图引擎 | Fur - + @@ -26,7 +26,7 @@
    - + diff --git a/handbook/build/f9353588.35659a55.js b/handbook/build/f9353588.35659a55.js deleted file mode 100644 index c2bfe4d7b6b..00000000000 --- a/handbook/build/f9353588.35659a55.js +++ /dev/null @@ -1 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[75],{130:function(e,n,t){"use strict";t.r(n),t.d(n,"frontMatter",(function(){return s})),t.d(n,"metadata",(function(){return c})),t.d(n,"rightToc",(function(){return p})),t.d(n,"default",(function(){return b}));var r=t(2),a=t(6),i=(t(0),t(138)),o=t(140),s={id:"get-start",title:"2. \u4e00\u5206\u949f\u5165\u95e8",sidebar_label:"2. \u4e00\u5206\u949f\u5165\u95e8"},c={unversionedId:"get-start",id:"get-start",isDocsHomePage:!1,title:"2. \u4e00\u5206\u949f\u5165\u95e8",description:"2.1 Hello Fur",source:"@site/docs\\get-start.mdx",slug:"/get-start",permalink:"/fur/docs/get-start",editUrl:"https://gitee.com/monksoul/Fur/tree/main/handbook/docs/get-start.mdx",version:"current",sidebar_label:"2. \u4e00\u5206\u949f\u5165\u95e8",sidebar:"docs",previous:{title:"1.3 \u5173\u4e8e\u4f5c\u8005",permalink:"/fur/docs/author"},next:{title:"3. \u5e94\u7528\u542f\u52a8",permalink:"/fur/docs/appstartup"}},p=[{value:"2.1 Hello Fur",id:"21-hello-fur",children:[{value:"2.1.1 \u521b\u5efa FurService \u7c7b",id:"211-\u521b\u5efa-furservice-\u7c7b",children:[]},{value:"2.1.2 \u5728\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b\u6548\u679c",id:"212-\u5728\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b\u6548\u679c",children:[]}]},{value:"2.2 \u6dfb\u52a0\u6570\u636e\u5e93\u652f\u6301",id:"22-\u6dfb\u52a0\u6570\u636e\u5e93\u652f\u6301",children:[{value:"2.2.1 \u6dfb\u52a0 Person \u5b9e\u4f53\u7c7b",id:"221-\u6dfb\u52a0-person-\u5b9e\u4f53\u7c7b",children:[]},{value:"2.2.2 \u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"222-\u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"2.2.3 \u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32",id:"223-\u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32",children:[]},{value:"2.2.4 \u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"224-\u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"2.2.5 \u901a\u8fc7\u547d\u4ee4\u521b\u5efa\u6570\u636e\u5e93\u8868",id:"225-\u901a\u8fc7\u547d\u4ee4\u521b\u5efa\u6570\u636e\u5e93\u8868",children:[]}]},{value:"2.3 \u589e\u5220\u67e5\u6539\u5206\u9875\u4f8b\u5b50",id:"23-\u589e\u5220\u67e5\u6539\u5206\u9875\u4f8b\u5b50",children:[{value:"\u9644\u4e0a PersonDto",id:"\u9644\u4e0a-persondto",children:[]}]}],u={rightToc:p};function b(e){var n=e.components,t=Object(a.a)(e,["components"]);return Object(i.b)("wrapper",Object(r.a)({},u,t,{components:n,mdxType:"MDXLayout"}),Object(i.b)("h2",{id:"21-hello-fur"},"2.1 Hello Fur"),Object(i.b)("h3",{id:"211-\u521b\u5efa-furservice-\u7c7b"},"2.1.1 \u521b\u5efa ",Object(i.b)("inlineCode",{parentName:"h3"},"FurService")," \u7c7b"),Object(i.b)("p",null,"\u8bbe\u7f6e ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Web.Entry")," \u4e3a\u542f\u52a8\u9879\uff0c\u5e76\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Application")," \u4e2d\u521b\u5efa ",Object(i.b)("inlineCode",{parentName:"p"},"FurService")," \u7c7b\uff0c\u5e76\u8f93\u5165\u4ee5\u4e0b\u5185\u5bb9:"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs",metastring:"{1,5,6,12}","{1,5,6,12}":!0}),'using Fur.DynamicApiController;\n\nnamespace Fur.Application\n{\n [DynamicApiController] // \u8fd9\u91cc\u4f7f\u7528\u7279\u6027\u65b9\u5f0f\n public class FurService /*: IDynamicApiController*/ // \u4e5f\u53ef\u4ee5\u4f7f\u7528\u63a5\u53e3\u65b9\u5f0f\n {\n /// \n /// \u5411\u4e16\u754c\u95ee\u597d\n /// \n /// \n public string SayHello()\n {\n return $"Hello {nameof(Fur)}";\n }\n }\n}\n')),Object(i.b)("h3",{id:"212-\u5728\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b\u6548\u679c"},"2.1.2 \u5728\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b\u6548\u679c"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Web.Entry")," \u9879\u76ee\u4e2d\u9009\u62e9 ",Object(i.b)("inlineCode",{parentName:"p"},"wwwroot")," \u53f3\u952e\u9009\u62e9\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b")),Object(i.b)("img",{src:Object(o.a)("img/getstart1.png"),style:{height:400}}),Object(i.b)("p",null,"\u6548\u679c\u5982\u4e0b\uff1a"),Object(i.b)("img",{src:Object(o.a)("img/getstart2.gif")}),Object(i.b)("h2",{id:"22-\u6dfb\u52a0\u6570\u636e\u5e93\u652f\u6301"},"2.2 \u6dfb\u52a0\u6570\u636e\u5e93\u652f\u6301"),Object(i.b)("h3",{id:"221-\u6dfb\u52a0-person-\u5b9e\u4f53\u7c7b"},"2.2.1 \u6dfb\u52a0 ",Object(i.b)("inlineCode",{parentName:"h3"},"Person")," \u5b9e\u4f53\u7c7b"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Core")," \u4e2d\u65b0\u5efa ",Object(i.b)("inlineCode",{parentName:"p"},"Person")," \u5b9e\u4f53\u7c7b\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs",metastring:"{1,7}","{1,7}":!0}),"using Fur.DatabaseAccessor;\nusing System;\nusing System.ComponentModel.DataAnnotations;\n\nnamespace Fur.Core\n{\n public class Person : Entity // \u7ee7\u627f\u81ea Entity \u62bd\u8c61\u7c7b\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")),Object(i.b)("h3",{id:"222-\u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"2.2.2 \u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u4e2d\u6dfb\u52a0 ",Object(i.b)("inlineCode",{parentName:"p"},"FurDbContext")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs",metastring:"{1-2,6-7,13}","{1-2,6-7,13}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("DbConnectionString")] // \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32\n public class FurDbContext : AppDbContext // \u7ee7\u627f AppDbContext<> \u7c7b\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(i.b)("h3",{id:"223-\u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32"},"2.2.3 \u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u7684 ",Object(i.b)("inlineCode",{parentName:"p"},"dbsettings.json")," \u4e2d\u914d\u7f6e\u6570\u636e\u5e93\u8fde\u63a5\u5b57\u7b26\u4e32\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-json",metastring:'{2-4} title="Fur\\framework\\Fur.EntityFramework.Core\\dbsettings.json"',"{2-4}":!0,title:'"Fur\\framework\\Fur.EntityFramework.Core\\dbsettings.json"'}),'{\n "ConnectionStrings": {\n "DbConnectionString": "Server=localhost;Database=Fur;User=sa;Password=000000;MultipleActiveResultSets=True;",\n "Sqlite3ConnectionString": "Data Source=./Fur.db"\n }\n}\n')),Object(i.b)("h3",{id:"224-\u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"2.2.4 \u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u7684 ",Object(i.b)("inlineCode",{parentName:"p"},"FurEntityFrameworkCoreStartup")," \u4e2d\u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs",metastring:'{12-14} title="Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"',"{12-14}":!0,title:'"Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"'}),"using Fur.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.EntityFramework.Core\n{\n [Startup(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 options.AddDbPool(DbProvider.Sqlite);\n });\n }\n }\n}\n")),Object(i.b)("div",{className:"admonition admonition-important alert alert--info"},Object(i.b)("div",Object(r.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(r.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(r.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(r.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u8bf4\u660e")),Object(i.b)("div",Object(r.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6f14\u793a\u793a\u4f8b\u4e2d\uff0c\u9ed8\u8ba4\u5df2\u7ecf\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u5c42\u5b89\u88c5\u4e86 ",Object(i.b)("inlineCode",{parentName:"p"},"Microsoft.EntityFrameworkCore.Sqlite")," \u5305\u3002"),Object(i.b)("p",{parentName:"div"},"\u5982\u679c\u4f60\u9700\u8981\u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93\u7248\u672c\uff0c\u53ef\u4ee5\u67e5\u9605 \u3010",Object(i.b)("a",Object(r.a)({parentName:"p"},{href:"dbcontext-multi-database"}),"9.18 \u591a\u6570\u636e\u5e93\u64cd\u4f5c"),"\u3011 \u7ae0\u8282\u3002"))),Object(i.b)("h3",{id:"225-\u901a\u8fc7\u547d\u4ee4\u521b\u5efa\u6570\u636e\u5e93\u8868"},"2.2.5 \u901a\u8fc7\u547d\u4ee4\u521b\u5efa\u6570\u636e\u5e93\u8868"),Object(i.b)("p",null,"\u6253\u5f00 ",Object(i.b)("inlineCode",{parentName:"p"},"\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0"),"\uff0c\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),Object(i.b)("img",{src:Object(o.a)("img/getstart3.png"),style:{height:400}}),Object(i.b)("p",null,"\u9009\u62e9 ",Object(i.b)("inlineCode",{parentName:"p"},"\u9ed8\u8ba4\u9879\u76ee\u4e3a"),"\uff1a",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Database.Migrations"),"\uff0c\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),Object(i.b)("img",{src:Object(o.a)("img/getstart4.png")}),Object(i.b)("p",null,Object(i.b)("strong",{parentName:"p"},"\u8f93\u5165\u4ee5\u4e0b\u547d\u4ee4"),"\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{}),"Add-Migration v0.0.1\n")),Object(i.b)("img",{src:Object(o.a)("img/getstart5.png")}),Object(i.b)("p",null,Object(i.b)("strong",{parentName:"p"},"\u63d0\u4ea4\u5230\u6570\u636e\u5e93\u66f4\u6539")),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{}),"Update-Database\n")),Object(i.b)("img",{src:Object(o.a)("img/getstart6.png")}),Object(i.b)("img",{src:Object(o.a)("img/getstart7.png"),style:{height:400}}),Object(i.b)("h2",{id:"23-\u589e\u5220\u67e5\u6539\u5206\u9875\u4f8b\u5b50"},"2.3 \u589e\u5220\u67e5\u6539\u5206\u9875\u4f8b\u5b50"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs",metastring:"{14-19}","{14-19}":!0}),'using Fur.Core;\nusing Fur.DatabaseAccessor;\nusing Fur.DynamicApiController;\nusing Mapster;\nusing Microsoft.EntityFrameworkCore;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\n\nnamespace Fur.Application\n{\n [DynamicApiController] // \u8fd9\u91cc\u4f7f\u7528\u7279\u6027\u65b9\u5f0f\n public class FurService /*: IDynamicApiController*/ // \u4e5f\u53ef\u4ee5\u4f7f\u7528\u63a5\u53e3\u65b9\u5f0f\n {\n // \u521d\u59cb\u5316\u4ed3\u50a8\n private readonly IRepository _personRepository;\n public FurService(IRepository personRepository)\n {\n _personRepository = personRepository;\n }\n\n /// \n /// \u65b0\u589e\u4e00\u6761\n /// \n public async Task Insert(PersonDto personDto)\n {\n // \u5982\u679c\u4e0d\u9700\u8981\u8fd4\u56de\u81ea\u589eId\uff0c\u4f7f\u7528 InsertAsync\u5373\u53ef\n var newEntity = await _personRepository.InsertNowAsync(personDto.Adapt());\n return newEntity.Entity.Id;\n\n // \u8fd8\u53ef\u4ee5\u76f4\u63a5\u64cd\u4f5c\n // await personDto.Adapt().InsertNowAsync();\n }\n\n /// \n /// \u66f4\u65b0\u4e00\u6761\n /// \n /// \n public async Task Update(PersonDto personDto)\n {\n await _personRepository.UpdateAsync(personDto.Adapt());\n\n // \u8fd8\u53ef\u4ee5\u76f4\u63a5\u64cd\u4f5c\n // await personDto.Adapt().UpdateAsync();\n }\n\n /// \n /// \u5220\u9664\u4e00\u6761\n /// \n /// \n public async Task Delete(int id)\n {\n await _personRepository.DeleteAsync(id);\n }\n\n /// \n /// \u67e5\u8be2\u4e00\u6761\n /// \n /// \n public async Task Find(int id)\n {\n var person = await _personRepository.FindAsync(id);\n return person.Adapt();\n }\n\n /// \n /// \u67e5\u8be2\u6240\u6709\n /// \n /// \n public async Task> GetAll()\n {\n var persons = await _personRepository.AsAsyncEnumerable();\n return persons.Adapt>();\n }\n\n /// \n /// \u5206\u9875\u67e5\u8be2\n /// \n /// \n /// \n /// \n public async Task> GetAllByPage(int pageIndex = 1, int pageSize = 10)\n {\n var pageResult = await _personRepository.AsQueryable().ToPagedListAsync(pageIndex, pageSize);\n return pageResult.Adapt>();\n }\n }\n}\n')),Object(i.b)("img",{src:Object(o.a)("img/getstart8.gif")}),Object(i.b)("h3",{id:"\u9644\u4e0a-persondto"},"\u9644\u4e0a ",Object(i.b)("inlineCode",{parentName:"h3"},"PersonDto")),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs"}),"using System.ComponentModel.DataAnnotations;\n\nnamespace Fur.Application\n{\n public class PersonDto\n {\n /// \n /// Id\n /// \n public int? Id { get; set; }\n\n /// \n /// \u59d3\u540d\n /// \n [StringLength(32, MinimumLength = 2)]\n public string Name { get; set; }\n\n /// \n /// \u5e74\u9f84\n /// \n public int Age { get; set; }\n }\n}\n")),Object(i.b)("p",null,"\u8bf4\u597d\u4e00\u5206\u949f\u5165\u95e8\uff0c\u4f60\u4eec\u7528\u4e86\u591a\u957f\u65f6\u95f4\u3002\ud83d\ude01"))}b.isMDXComponent=!0},138:function(e,n,t){"use strict";t.d(n,"a",(function(){return b})),t.d(n,"b",(function(){return d}));var r=t(0),a=t.n(r);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 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 p=a.a.createContext({}),u=function(e){var n=a.a.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},b=function(e){var n=u(e.components);return a.a.createElement(p.Provider,{value:n},e.children)},l={inlineCode:"code",wrapper:function(e){var n=e.children;return a.a.createElement(a.a.Fragment,{},n)}},m=a.a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,i=e.originalType,o=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),b=u(t),m=r,d=b["".concat(o,".").concat(m)]||b[m]||l[m]||i;return t?a.a.createElement(d,s(s({ref:n},p),{},{components:t})):a.a.createElement(d,s({ref:n},p))}));function d(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var i=t.length,o=new Array(i);o[0]=m;var s={};for(var c in n)hasOwnProperty.call(n,c)&&(s[c]=n[c]);s.originalType=e,s.mdxType="string"==typeof e?e:r,o[1]=s;for(var p=2;pfunction(e,n,t,{forcePrependBaseUrl:r=!1,absolute:i=!1}={}){if(!t)return t;if(t.startsWith("#"))return t;if(Object(a.b)(t))return t;if(r)return n+t;const o=t.startsWith(n)?t:n+t.replace(/^\//,"");return i?e+o:o}(n,e,t,r)}}function o(e,n={}){const{withBaseUrl:t}=i();return t(e,n)}},141:function(e,n,t){"use strict";function r(e){return!0===/^(\w*:|\/\/)/.test(e)}function a(e){return void 0!==e&&!r(e)}t.d(n,"b",(function(){return r})),t.d(n,"a",(function(){return a}))}}]); \ No newline at end of file diff --git a/handbook/build/f9353588.433ee201.js b/handbook/build/f9353588.433ee201.js new file mode 100644 index 00000000000..4f26884ea76 --- /dev/null +++ b/handbook/build/f9353588.433ee201.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[75],{130:function(e,n,t){"use strict";t.r(n),t.d(n,"frontMatter",(function(){return s})),t.d(n,"metadata",(function(){return c})),t.d(n,"rightToc",(function(){return p})),t.d(n,"default",(function(){return b}));var r=t(2),a=t(6),i=(t(0),t(138)),o=t(140),s={id:"get-start",title:"2. \u4e00\u5206\u949f\u5165\u95e8",sidebar_label:"2. \u4e00\u5206\u949f\u5165\u95e8"},c={unversionedId:"get-start",id:"get-start",isDocsHomePage:!1,title:"2. \u4e00\u5206\u949f\u5165\u95e8",description:"2.1 Hello Fur",source:"@site/docs\\get-start.mdx",slug:"/get-start",permalink:"/fur/docs/get-start",editUrl:"https://gitee.com/monksoul/Fur/tree/main/handbook/docs/get-start.mdx",version:"current",sidebar_label:"2. \u4e00\u5206\u949f\u5165\u95e8",sidebar:"docs",previous:{title:"1.3 \u5173\u4e8e\u4f5c\u8005",permalink:"/fur/docs/author"},next:{title:"3. \u5e94\u7528\u542f\u52a8",permalink:"/fur/docs/appstartup"}},p=[{value:"2.1 Hello Fur",id:"21-hello-fur",children:[{value:"2.1.1 \u521b\u5efa FurService \u7c7b",id:"211-\u521b\u5efa-furservice-\u7c7b",children:[]},{value:"2.1.2 \u5728\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b\u6548\u679c",id:"212-\u5728\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b\u6548\u679c",children:[]}]},{value:"2.2 \u6dfb\u52a0\u6570\u636e\u5e93\u652f\u6301",id:"22-\u6dfb\u52a0\u6570\u636e\u5e93\u652f\u6301",children:[{value:"2.2.1 \u6dfb\u52a0 Person \u5b9e\u4f53\u7c7b",id:"221-\u6dfb\u52a0-person-\u5b9e\u4f53\u7c7b",children:[]},{value:"2.2.2 \u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"222-\u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"2.2.3 \u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",id:"223-\u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587",children:[]},{value:"2.2.4 \u901a\u8fc7\u547d\u4ee4\u521b\u5efa\u6570\u636e\u5e93\u8868",id:"224-\u901a\u8fc7\u547d\u4ee4\u521b\u5efa\u6570\u636e\u5e93\u8868",children:[]}]},{value:"2.3 \u589e\u5220\u67e5\u6539\u5206\u9875\u4f8b\u5b50",id:"23-\u589e\u5220\u67e5\u6539\u5206\u9875\u4f8b\u5b50",children:[{value:"\u9644\u4e0a PersonDto",id:"\u9644\u4e0a-persondto",children:[]}]}],u={rightToc:p};function b(e){var n=e.components,t=Object(a.a)(e,["components"]);return Object(i.b)("wrapper",Object(r.a)({},u,t,{components:n,mdxType:"MDXLayout"}),Object(i.b)("h2",{id:"21-hello-fur"},"2.1 Hello Fur"),Object(i.b)("h3",{id:"211-\u521b\u5efa-furservice-\u7c7b"},"2.1.1 \u521b\u5efa ",Object(i.b)("inlineCode",{parentName:"h3"},"FurService")," \u7c7b"),Object(i.b)("p",null,"\u8bbe\u7f6e ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Web.Entry")," \u4e3a\u542f\u52a8\u9879\uff0c\u5e76\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Application")," \u4e2d\u521b\u5efa ",Object(i.b)("inlineCode",{parentName:"p"},"FurService")," \u7c7b\uff0c\u5e76\u8f93\u5165\u4ee5\u4e0b\u5185\u5bb9:"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs",metastring:"{1,5,6,12}","{1,5,6,12}":!0}),'using Fur.DynamicApiController;\n\nnamespace Fur.Application\n{\n [DynamicApiController] // \u8fd9\u91cc\u4f7f\u7528\u7279\u6027\u65b9\u5f0f\n public class FurService /*: IDynamicApiController*/ // \u4e5f\u53ef\u4ee5\u4f7f\u7528\u63a5\u53e3\u65b9\u5f0f\n {\n /// \n /// \u5411\u4e16\u754c\u95ee\u597d\n /// \n /// \n public string SayHello()\n {\n return $"Hello {nameof(Fur)}";\n }\n }\n}\n')),Object(i.b)("h3",{id:"212-\u5728\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b\u6548\u679c"},"2.1.2 \u5728\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b\u6548\u679c"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Web.Entry")," \u9879\u76ee\u4e2d\u9009\u62e9 ",Object(i.b)("inlineCode",{parentName:"p"},"wwwroot")," \u53f3\u952e\u9009\u62e9\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"\u6d4f\u89c8\u5668\u4e2d\u67e5\u770b")),Object(i.b)("img",{src:Object(o.a)("img/getstart1.png"),style:{height:400}}),Object(i.b)("p",null,"\u6548\u679c\u5982\u4e0b\uff1a"),Object(i.b)("img",{src:Object(o.a)("img/getstart2.gif")}),Object(i.b)("h2",{id:"22-\u6dfb\u52a0\u6570\u636e\u5e93\u652f\u6301"},"2.2 \u6dfb\u52a0\u6570\u636e\u5e93\u652f\u6301"),Object(i.b)("h3",{id:"221-\u6dfb\u52a0-person-\u5b9e\u4f53\u7c7b"},"2.2.1 \u6dfb\u52a0 ",Object(i.b)("inlineCode",{parentName:"h3"},"Person")," \u5b9e\u4f53\u7c7b"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Core")," \u4e2d\u65b0\u5efa ",Object(i.b)("inlineCode",{parentName:"p"},"Person")," \u5b9e\u4f53\u7c7b\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs",metastring:"{1,7}","{1,7}":!0}),"using Fur.DatabaseAccessor;\nusing System;\nusing System.ComponentModel.DataAnnotations;\n\nnamespace Fur.Core\n{\n public class Person : Entity // \u7ee7\u627f\u81ea Entity \u62bd\u8c61\u7c7b\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")),Object(i.b)("h3",{id:"222-\u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"2.2.2 \u521b\u5efa\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u4e2d\u6dfb\u52a0 ",Object(i.b)("inlineCode",{parentName:"p"},"FurDbContext")," \u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs",metastring:"{1-2,6-7,13}","{1-2,6-7,13}":!0}),'using Fur.DatabaseAccessor;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace Fur.EntityFramework.Core\n{\n [AppDbContext("Data Source=./Fur.db")] // \u914d\u7f6e\u8fde\u63a5\u5b57\u7b26\u4e32\n public class FurDbContext : AppDbContext // \u7ee7\u627f AppDbContext<> \u7c7b\n {\n /// \n /// \u7ee7\u627f\u7236\u7c7b\u6784\u9020\u51fd\u6570\n /// \n /// \n public FurDbContext(DbContextOptions options) : base(options)\n {\n }\n }\n}\n')),Object(i.b)("h3",{id:"223-\u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"},"2.2.3 \u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587"),Object(i.b)("p",null,"\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u7684 ",Object(i.b)("inlineCode",{parentName:"p"},"FurEntityFrameworkCoreStartup")," \u4e2d\u914d\u7f6e\u6570\u636e\u5e93\u4e0a\u4e0b\u6587\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs",metastring:'{11-14} title="Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"',"{11-14}":!0,title:'"Fur\\framework\\Fur.EntityFramework.Core\\FurEntityFrameworkCoreStartup.cs"'}),"using Fur.DatabaseAccessor;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Fur.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")),Object(i.b)("div",{className:"admonition admonition-important alert alert--info"},Object(i.b)("div",Object(r.a)({parentName:"div"},{className:"admonition-heading"}),Object(i.b)("h5",{parentName:"div"},Object(i.b)("span",Object(r.a)({parentName:"h5"},{className:"admonition-icon"}),Object(i.b)("svg",Object(r.a)({parentName:"span"},{xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"}),Object(i.b)("path",Object(r.a)({parentName:"svg"},{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"})))),"\u7279\u522b\u8bf4\u660e")),Object(i.b)("div",Object(r.a)({parentName:"div"},{className:"admonition-content"}),Object(i.b)("p",{parentName:"div"},Object(i.b)("inlineCode",{parentName:"p"},"Fur")," \u6f14\u793a\u793a\u4f8b\u4e2d\uff0c\u9ed8\u8ba4\u5df2\u7ecf\u5728 ",Object(i.b)("inlineCode",{parentName:"p"},"Fur.EntityFramework.Core")," \u5c42\u5b89\u88c5\u4e86 ",Object(i.b)("inlineCode",{parentName:"p"},"Microsoft.EntityFrameworkCore.Sqlite")," \u5305\u3002"),Object(i.b)("p",{parentName:"div"},"\u5982\u679c\u4f60\u9700\u8981\u5b89\u88c5\u5bf9\u5e94\u7684\u6570\u636e\u5e93\u7248\u672c\uff0c\u53ef\u4ee5\u67e5\u9605 \u3010",Object(i.b)("a",Object(r.a)({parentName:"p"},{href:"dbcontext-multi-database"}),"9.18 \u591a\u6570\u636e\u5e93\u64cd\u4f5c"),"\u3011 \u7ae0\u8282\u3002"))),Object(i.b)("h3",{id:"224-\u901a\u8fc7\u547d\u4ee4\u521b\u5efa\u6570\u636e\u5e93\u8868"},"2.2.4 \u901a\u8fc7\u547d\u4ee4\u521b\u5efa\u6570\u636e\u5e93\u8868"),Object(i.b)("p",null,"\u6253\u5f00 ",Object(i.b)("inlineCode",{parentName:"p"},"\u7a0b\u5e8f\u5305\u7ba1\u7406\u63a7\u5236\u53f0"),"\uff0c\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),Object(i.b)("img",{src:Object(o.a)("img/getstart3.png"),style:{height:400}}),Object(i.b)("p",null,"\u9009\u62e9 ",Object(i.b)("inlineCode",{parentName:"p"},"\u9ed8\u8ba4\u9879\u76ee\u4e3a"),"\uff1a",Object(i.b)("inlineCode",{parentName:"p"},"Fur.Database.Migrations"),"\uff0c\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),Object(i.b)("img",{src:Object(o.a)("img/getstart4.png")}),Object(i.b)("p",null,Object(i.b)("strong",{parentName:"p"},"\u8f93\u5165\u4ee5\u4e0b\u547d\u4ee4"),"\uff1a"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{}),"Add-Migration v0.0.1\n")),Object(i.b)("img",{src:Object(o.a)("img/getstart5.png")}),Object(i.b)("p",null,Object(i.b)("strong",{parentName:"p"},"\u63d0\u4ea4\u5230\u6570\u636e\u5e93\u66f4\u6539")),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{}),"Update-Database\n")),Object(i.b)("img",{src:Object(o.a)("img/getstart6.png")}),Object(i.b)("img",{src:Object(o.a)("img/getstart7.png"),style:{height:400}}),Object(i.b)("h2",{id:"23-\u589e\u5220\u67e5\u6539\u5206\u9875\u4f8b\u5b50"},"2.3 \u589e\u5220\u67e5\u6539\u5206\u9875\u4f8b\u5b50"),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs",metastring:"{14-19}","{14-19}":!0}),'using Fur.Core;\nusing Fur.DatabaseAccessor;\nusing Fur.DynamicApiController;\nusing Mapster;\nusing Microsoft.EntityFrameworkCore;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\n\nnamespace Fur.Application\n{\n [DynamicApiController] // \u8fd9\u91cc\u4f7f\u7528\u7279\u6027\u65b9\u5f0f\n public class FurService /*: IDynamicApiController*/ // \u4e5f\u53ef\u4ee5\u4f7f\u7528\u63a5\u53e3\u65b9\u5f0f\n {\n // \u521d\u59cb\u5316\u4ed3\u50a8\n private readonly IRepository _personRepository;\n public FurService(IRepository personRepository)\n {\n _personRepository = personRepository;\n }\n\n /// \n /// \u65b0\u589e\u4e00\u6761\n /// \n public async Task Insert(PersonDto personDto)\n {\n // \u5982\u679c\u4e0d\u9700\u8981\u8fd4\u56de\u81ea\u589eId\uff0c\u4f7f\u7528 InsertAsync\u5373\u53ef\n var newEntity = await _personRepository.InsertNowAsync(personDto.Adapt());\n return newEntity.Entity.Id;\n\n // \u8fd8\u53ef\u4ee5\u76f4\u63a5\u64cd\u4f5c\n // await personDto.Adapt().InsertNowAsync();\n }\n\n /// \n /// \u66f4\u65b0\u4e00\u6761\n /// \n /// \n public async Task Update(PersonDto personDto)\n {\n await _personRepository.UpdateAsync(personDto.Adapt());\n\n // \u8fd8\u53ef\u4ee5\u76f4\u63a5\u64cd\u4f5c\n // await personDto.Adapt().UpdateAsync();\n }\n\n /// \n /// \u5220\u9664\u4e00\u6761\n /// \n /// \n public async Task Delete(int id)\n {\n await _personRepository.DeleteAsync(id);\n }\n\n /// \n /// \u67e5\u8be2\u4e00\u6761\n /// \n /// \n public async Task Find(int id)\n {\n var person = await _personRepository.FindAsync(id);\n return person.Adapt();\n }\n\n /// \n /// \u67e5\u8be2\u6240\u6709\n /// \n /// \n public async Task> GetAll()\n {\n var persons = await _personRepository.AsAsyncEnumerable();\n return persons.Adapt>();\n }\n\n /// \n /// \u5206\u9875\u67e5\u8be2\n /// \n /// \n /// \n /// \n public async Task> GetAllByPage(int pageIndex = 1, int pageSize = 10)\n {\n var pageResult = await _personRepository.AsQueryable().ToPagedListAsync(pageIndex, pageSize);\n return pageResult.Adapt>();\n }\n }\n}\n')),Object(i.b)("img",{src:Object(o.a)("img/getstart8.gif")}),Object(i.b)("h3",{id:"\u9644\u4e0a-persondto"},"\u9644\u4e0a ",Object(i.b)("inlineCode",{parentName:"h3"},"PersonDto")),Object(i.b)("pre",null,Object(i.b)("code",Object(r.a)({parentName:"pre"},{className:"language-cs"}),"using System.ComponentModel.DataAnnotations;\n\nnamespace Fur.Application\n{\n public class PersonDto\n {\n /// \n /// Id\n /// \n public int? Id { get; set; }\n\n /// \n /// \u59d3\u540d\n /// \n [StringLength(32, MinimumLength = 2)]\n public string Name { get; set; }\n\n /// \n /// \u5e74\u9f84\n /// \n public int Age { get; set; }\n }\n}\n")),Object(i.b)("p",null,"\u8bf4\u597d\u4e00\u5206\u949f\u5165\u95e8\uff0c\u4f60\u4eec\u7528\u4e86\u591a\u957f\u65f6\u95f4\u3002\ud83d\ude01"))}b.isMDXComponent=!0},138:function(e,n,t){"use strict";t.d(n,"a",(function(){return b})),t.d(n,"b",(function(){return d}));var r=t(0),a=t.n(r);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 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 p=a.a.createContext({}),u=function(e){var n=a.a.useContext(p),t=n;return e&&(t="function"==typeof e?e(n):s(s({},n),e)),t},b=function(e){var n=u(e.components);return a.a.createElement(p.Provider,{value:n},e.children)},l={inlineCode:"code",wrapper:function(e){var n=e.children;return a.a.createElement(a.a.Fragment,{},n)}},m=a.a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,i=e.originalType,o=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),b=u(t),m=r,d=b["".concat(o,".").concat(m)]||b[m]||l[m]||i;return t?a.a.createElement(d,s(s({ref:n},p),{},{components:t})):a.a.createElement(d,s({ref:n},p))}));function d(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var i=t.length,o=new Array(i);o[0]=m;var s={};for(var c in n)hasOwnProperty.call(n,c)&&(s[c]=n[c]);s.originalType=e,s.mdxType="string"==typeof e?e:r,o[1]=s;for(var p=2;pfunction(e,n,t,{forcePrependBaseUrl:r=!1,absolute:i=!1}={}){if(!t)return t;if(t.startsWith("#"))return t;if(Object(a.b)(t))return t;if(r)return n+t;const o=t.startsWith(n)?t:n+t.replace(/^\//,"");return i?e+o:o}(n,e,t,r)}}function o(e,n={}){const{withBaseUrl:t}=i();return t(e,n)}},141:function(e,n,t){"use strict";function r(e){return!0===/^(\w*:|\/\/)/.test(e)}function a(e){return void 0!==e&&!r(e)}t.d(n,"b",(function(){return r})),t.d(n,"a",(function(){return a}))}}]); \ No newline at end of file diff --git a/handbook/build/index.html b/handbook/build/index.html index 6525d78dd95..b5b5242b283 100644 --- a/handbook/build/index.html +++ b/handbook/build/index.html @@ -6,7 +6,7 @@ Fur 是 .NET 5 平台下极易入门、极速开发的 Web 应用框架。 Fur | Fur - + @@ -22,7 +22,7 @@

    Fur 是 .NET 5 平台下极易入门、极速开发的 Web 应用框架。

    [object Object]

    .NET 5 新起点

    .NET 5 是 .NET 的重要且令人兴奋的新方向。你会看到 .NET 变得更加简单,但也有更广泛的功能和实用程序。所有新的开发和功能都将是 .NET 5 的一部分,包括新的 C# 版本

    [object Object]

    “六级” 架构

    Fur 在设计之初就秉承着 “六极” :极易入门、极速开发、极少依赖、极少配置、极其灵活、极易维护 的设计思想,在架构设计上做了大量的优化,支持各个能力阶层技术员极速上手。

    [object Object]

    冲一杯咖啡的时间

    Fur 除了独具创新的设计理念和灵活的架构设计以外,同时还结合了主流的敏捷开发模式打造的一款极速开发框架。只需冲制一杯咖啡的时间便可完成工作

    - + diff --git a/handbook/build/runtime~main.f6cd1698.js b/handbook/build/runtime~main.1ff2adeb.js similarity index 65% rename from handbook/build/runtime~main.f6cd1698.js rename to handbook/build/runtime~main.1ff2adeb.js index 7fdacebb320..5049defc08c 100644 --- a/handbook/build/runtime~main.f6cd1698.js +++ b/handbook/build/runtime~main.1ff2adeb.js @@ -1 +1 @@ -!function(e){function a(a){for(var c,r,t=a[0],n=a[1],o=a[2],u=0,l=[];u + { + webBuilder.Inject() + .UseStartup(); + }); + } + } +} +``` + +### 3.1.1 `Startup` 两个重要方法 + +`Startup` 默认有两个重要的方法: + +- `ConfigureServices`:配置应用所需服务,在该方法中可以添加应用所需要的功能或服务 +- `Configure`:配置应用请求处理管道 + +默认代码如下: + +```cs {9,13} title="Fur.Web.Entry\Startup.cs" +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; + +namespace Fur.Web.Entry +{ + public class Startup + { + public void ConfigureServices(IServiceCollection services) + { + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + } + } +} +``` + +在这里,不打算详细讲 `Startup` 类的具体功能和作用。 + +:::note 了解更多 + +想了解更多 `Startup` 知识可查阅 [ASP.NET Core - Startup 类](https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/startup?view=aspnetcore-3.1) 章节。 + +::: + +## 3.2 `AppStartup` + +在 `Fur` 框架中,提供了更为灵活的 `Startup` 类配置方式,无需在 `Web 启用层` 中配置,可将配置放到任何项目层。 + +可能会有读者有疑问,为什么要多此一举呢?原因有几点: + +- `Startup` 类默认和 `Web 应用层` 绑定在一起,这样就会导致如果我创建了新的 `Web 应用层`,`Startup` 又要重新配置 +- 随着业务的增长,需要集成越来越多的第三方服务,这时候 `Startup` 类就会变得越来越臃肿,难以维护 +- `Startup` 类无法其他项目类型进行共用 + +所以,`Fur` 提供了更加灵活的配置方式:`AppStartup`。 + +### 3.2.1 如何配置 `AppStartup` + +`AppStartup` 是一个抽象的空类,没有任何定义成员。正是因为这样,才提供更加灵活的配置方式。 + +### 3.2.2 `AppStartup` 约定 + +`AppStartup` 派生类只有两个小约定: + +- 任何公开、非静态、返回值为 `void` 且方法第一个参数是 `IServiceCollection` 类型,那么他就是一个 `ConfigureServices` 方法 +- 任何公开、非静态、返回值为 `void` 且方法第一个参数是 `IApplicationBuilder` 类型,第二个参数是 `IWebHostEnvironment` 类型,那么他就是一个 `Configure` 方法 + +所以,我们可以自由的编写方法,只要遵循约定即可,如: + +```cs {5,7,12,18,23} +using Microsoft.Extensions.DependencyInjection; + +namespace Fur.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.2.3 `AppStartup` 配置顺序 + +默认情况下,`AppStartup` 配置顺序由所在程序集的名称进行正序调用,如果我们需要配置执行顺序,只需要在 `AppStartup` 派生类中贴 `[AppStartup(order)]` 特性即可。 + +`order` 数值越大,约在前面调用,如: + +```cs {5} +using Microsoft.Extensions.DependencyInjection; + +namespace Fur.EntityFramework.Core +{ + [AppStartup(10)] + public class FirstStartup : AppStartup + { + public void ConfigureServices(IServiceCollection services) + { + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + } + } +} +``` + +```cs {5} +using Microsoft.Extensions.DependencyInjection; + +namespace Fur.EntityFramework.Core +{ + [AppStartup(9)] + public class SecondStartup : AppStartup + { + public void ConfigureServices(IServiceCollection services) + { + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + } + } +} +``` + +`FirstStartup` 会在 `SecondStartup` 之前调用。 + +### 3.2.4 `AppStartup` 方法调用顺序 + +`AppStartup` 方法调用顺序和方法的书写先后有关,越在前面的方法越先调用。 + +## 3.3 框架默认 `AppStartup` 实现 + +`Fur` 框架默认在每一个项目层中都创建了一个 `AppStartup` 派生类,方便大家配置。如: + +- `FurStartup.cs`:`Fur` 框架核心启动类(通常无需配置) +- `FurApplicationStartup.cs`:业务服务启动类 +- `FurCoreStartup.cs`:应用核心功能启动类 +- `FurEntityFrameworkCoreStartup.cs`:数据库相关启动类 +- `FurWebCoreStartup.cs`:`Web` 核心启动配置类 + +## 3.4 `Startup` 配置最佳实践 + +建议 `Web` 启动层的 `Startup.cs` 保持为空方法体,如: + +```cs title="Fur.Web.Entry\Startup.cs" +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; + +namespace Fur.Web.Entry +{ + public class Startup + { + public void ConfigureServices(IServiceCollection services) + { + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + } + } +} +``` + +将所有 `Web 应用层` 配置迁移到 `FurWebCoreStartup.cs` 中,如: + +```cs title="Fur.Web.Core\FurWebCoreStartup.cs" +using Fur.UnifyResult; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace Fur.Web.Core +{ + [AppStartup(800)] + public sealed class FurWebCoreStartup : AppStartup + { + public void ConfigureServices(IServiceCollection services) + { + services.AddCorsAccessor(); + + services.AddSpecificationDocuments(); + services.AddControllers() + .AddDynamicApiControllers() + .AddDataValidation() + .AddFriendlyException() + .AddUnifyResult(); + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseHttpsRedirection(); + + app.UseRouting(); + + app.UseCorsAccessor(); + + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseSpecificationDocuments(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } + } +} +``` + +这样,后续更换 `Web 应用层` 也无需重新配置 `Startup.cs` + +## 3.5 关于 `appsettings.json` + +在默认情况下,`ASP.NET Core` 配置放在 `appsettings.json` 中配置,但是这样的方式和 `Startup.cs` 配置一样的道理,一旦我们更换了 `Web 应用层`,那么 `appsettings.json` 又要重新配置一次。 + +所以,`Fur` 框架提供了更加灵活的方式配置 `appsettings.json`,**只需要在任何项目层根目录下创建 `.json` 文件即可** + +**`Fur` 框架最后会自动合并所有分散的配置文件。** + +如我们在 `Fur.EntityFramework.Core` 层创建 `dbsettings.json` 配置数据库连接字符串,如: + +```json title="Fur.EntityFramework.Core\dbsettings.json" +{ + "ConnectionStrings": { + "DbConnectionString": "Server=localhost;Database=Fur;User=sa;Password=000000;MultipleActiveResultSets=True;", + "Sqlite3ConnectionString": "Data Source=./Fur.db" + } +} +``` + +**无需在 `appsettings.json` 中配置**,下面是 `appsettings.json` 默认代码: + +```json +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information", + "Microsoft.EntityFrameworkCore": "Information" + } + }, + "AllowedHosts": "*" +} +``` + +这样我们把配置文件分散在不同项目层之后,就可以实现共用和共享了。 + +## 3.6 神奇的 `Inject()` + +`Inject()` 方法是 `Fur` 框架提供的最小侵入式的方法,可以让任何 `ASP.NET Core` Web项目瞬间支持所有 `Fur` 框架特性。 + +我们创建了新的 `Web 项目`,只需要两个步骤即可: + +- 添加 `Fur.Web.Core` 项目引用 +- 在 `Program.cs` 中调用即可 + +如: + +```cs {18} +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; + +namespace Fur.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(); + }); + } + } +} +``` + +非常简单吧。我们后续创建任何 `MVC`,`RazorPages`,`Blazor` 项目只需要添加 `Fur.Web.Core` 引用和调用 `Inject()` 即可。 + +## 3.7 反馈与建议 + +:::note 与我们交流 + +给 Fur 提 [Issue](https://gitee.com/monksoul/Fur/issues/new?issue)。 + +::: \ No newline at end of file diff --git a/handbook/docs/dbcontext-Interceptor.mdx b/handbook/docs/dbcontext-Interceptor.mdx index 94db8924dda..5d18578464c 100644 --- a/handbook/docs/dbcontext-Interceptor.mdx +++ b/handbook/docs/dbcontext-Interceptor.mdx @@ -6,7 +6,7 @@ sidebar_label: 9.24 数据库操作拦截器 ## 9.24.1 数据库拦截器 -`Fur` 框架提供三种数据库操作拦截器,可以通过拦截器动态修改数据库连接字符串,动态修改sql,动态更改参数等操作。 +`Fur` 框架提供三种数据库操作拦截器,可以通过拦截器动态修该数据库连接字符串,动态修改sql,动态更改参数等操作。 目前支持这三种拦截器: diff --git a/handbook/docs/dbcontext-read-write.mdx b/handbook/docs/dbcontext-read-write.mdx index 0dc4e4eca01..f0123613ce8 100644 --- a/handbook/docs/dbcontext-read-write.mdx +++ b/handbook/docs/dbcontext-read-write.mdx @@ -125,7 +125,7 @@ using Microsoft.Extensions.DependencyInjection; namespace Fur.EntityFramework.Core { - [Startup(600)] + [AppStartup(600)] public sealed class FurEntityFrameworkCoreStartup : AppStartup { public void ConfigureServices(IServiceCollection services) diff --git a/handbook/docs/dbcontext.mdx b/handbook/docs/dbcontext.mdx index 78f21a11a63..788e79b67bf 100644 --- a/handbook/docs/dbcontext.mdx +++ b/handbook/docs/dbcontext.mdx @@ -106,7 +106,7 @@ using Microsoft.Extensions.DependencyInjection; namespace Fur.EntityFramework.Core { - [Startup(600)] + [AppStartup(600)] public sealed class FurEntityFrameworkCoreStartup : AppStartup { public void ConfigureServices(IServiceCollection services) @@ -205,7 +205,7 @@ namespace Fur.EntityFramework.Core ## 9.1.7 数据库上下文注册 -数据库上下文配置好数据库连接字符串后,需要注册改数据库上下文,并指定数据库类型,如: +数据库上下文配置好数据库连接字符串后,需要注册该数据库上下文,并指定数据库类型,如: ```cs {11-13} title="Fur\framework\Fur.EntityFramework.Core\FurEntityFrameworkCoreStartup.cs" using Fur.DatabaseAccessor; @@ -213,7 +213,7 @@ using Microsoft.Extensions.DependencyInjection; namespace Fur.EntityFramework.Core { - [Startup(600)] + [AppStartup(600)] public sealed class FurEntityFrameworkCoreStartup : AppStartup { public void ConfigureServices(IServiceCollection services) diff --git a/handbook/docs/get-start.mdx b/handbook/docs/get-start.mdx index ad1b31a1f20..e99054b296b 100644 --- a/handbook/docs/get-start.mdx +++ b/handbook/docs/get-start.mdx @@ -119,7 +119,7 @@ using Microsoft.Extensions.DependencyInjection; namespace Fur.EntityFramework.Core { - [Startup(600)] + [AppStartup(600)] public sealed class FurEntityFrameworkCoreStartup : AppStartup { public void ConfigureServices(IServiceCollection services) diff --git a/handbook/docs/saas.mdx b/handbook/docs/saas.mdx index dd924ab5da6..d11c611010b 100644 --- a/handbook/docs/saas.mdx +++ b/handbook/docs/saas.mdx @@ -92,7 +92,7 @@ using Microsoft.Extensions.DependencyInjection; namespace Fur.EntityFramework.Core { - [Startup(600)] + [AppStartup(600)] public sealed class FurEntityFrameworkCoreStartup : AppStartup { public void ConfigureServices(IServiceCollection services) @@ -319,7 +319,7 @@ using Microsoft.Extensions.DependencyInjection; namespace Fur.EntityFramework.Core { - [Startup(600)] + [AppStartup(600)] public sealed class FurEntityFrameworkCoreStartup : AppStartup { public void ConfigureServices(IServiceCollection services) @@ -487,7 +487,7 @@ using Microsoft.Extensions.DependencyInjection; namespace Fur.EntityFramework.Core { - [Startup(600)] + [AppStartup(600)] public sealed class FurEntityFrameworkCoreStartup : AppStartup { public void ConfigureServices(IServiceCollection services)