{"id":47323,"date":"2023-01-16T19:22:50","date_gmt":"2023-11-07T05:27:38","guid":{"rendered":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bb%a5%e4%b8%8b%e6%98%af%e5%b0%8f%e5%9e%8b%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e4%b8%adcqrs%e4%ba%8b%e4%bb%b6%e6%ba%af%e6%ba%90%e7%9a%84%e9%85%8d%e7%bd%ae%e7%a4%ba%e4%be%8b%ef%bc%9a\/"},"modified":"2024-04-29T10:09:35","modified_gmt":"2024-04-29T02:09:35","slug":"%e4%bb%a5%e4%b8%8b%e6%98%af%e5%b0%8f%e5%9e%8b%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e4%b8%adcqrs%e4%ba%8b%e4%bb%b6%e6%ba%af%e6%ba%90%e7%9a%84%e9%85%8d%e7%bd%ae%e7%a4%ba%e4%be%8b%ef%bc%9a","status":"publish","type":"post","link":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bb%a5%e4%b8%8b%e6%98%af%e5%b0%8f%e5%9e%8b%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e4%b8%adcqrs%e4%ba%8b%e4%bb%b6%e6%ba%af%e6%ba%90%e7%9a%84%e9%85%8d%e7%bd%ae%e7%a4%ba%e4%be%8b%ef%bc%9a\/","title":{"rendered":"\u4ee5\u4e0b\u662f\u5c0f\u578b\u5e94\u7528\u7a0b\u5e8f\u4e2dCQRS+\u4e8b\u4ef6\u6eaf\u6e90\u7684\u914d\u7f6e\u793a\u4f8b\uff1a"},"content":{"rendered":"<h1>\u7ecf\u8fc7<\/h1>\n<p>\u5f53\u8bd5\u56fe\u5728\u672c\u5730\u73af\u5883\u4e2d\u5b9e\u73b0CQRS+\u4e8b\u4ef6\u6eaf\u6e90\u65f6\uff0c\u6211\u8003\u8651\u5230\u662f\u5426\u53ef\u4ee5\u5728\u4e0d\u4f7f\u7528Apache Kafka\u7b49\u6d88\u606f\u961f\u5217\u7684\u60c5\u51b5\u4e0b\u5b9e\u73b0\u4e8b\u4ef6\u68c0\u6d4b\u3002\u6211\u60f3\u5230\u4f7f\u7528PostgreSQL\u7684Pub\/Sub\u529f\u80fd\u53ef\u80fd\u53ef\u4ee5\u5728\u6700\u5c0f\u7a0b\u5ea6\u4e0a\u5b9e\u73b0\uff0c\u6240\u4ee5\u6211\u505a\u4e86\u4e00\u4e2a\u8003\u8651\u5e94\u7528\u7a0b\u5e8f\u3002\u5e94\u7528\u7a0b\u5e8f\u53ef\u4ee5\u5728\u8fd9\u91cc\u627e\u5230\u3002<\/p>\n<p>\u5982\u679c\u514b\u9686\u4e86<\/p>\n<pre class=\"post-pre\"><code><span class=\"nb\">cd <\/span>src\r\ndocker-compose up <span class=\"nt\">-d<\/span> <span class=\"nt\">--build<\/span>\r\n<\/code><\/pre>\n<p>\u6211\u4f1a\u542f\u52a8\u3002<\/p>\n<h1>\u73af\u5883<\/h1>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">\u81ea\u4f5c\u691c\u8a0e\u30a2\u30d7\u30ea<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">docker-compose<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">mcr.microsoft.com\/dotnet\/sdk:7.0<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">Microsoft.EntityFrameworkCore Version=7.0.0-preview.7.22376.2<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">postgres:14.5-bullseye<\/ul>\n<h1>\u73af\u5883\u56fe\u50cf<\/h1>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">write_model(eventstore\u7528\u306epostgres)<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">read_model(\u53c2\u7167\u7528\u306epostgres)<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">\n<li style=\"list-style-type: none;\">\n<ul class=\"post-ul\">Projector(read_model\u3078\u30a4\u30d9\u30f3\u30c8\u3092\u5c04\u5f71\u3059\u308bdotnetcore)<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<ul class=\"post-ul\">SampleCmd(write_model\u3078\u30a4\u30d9\u30f3\u30c8\u3092\u8ffd\u52a0\u3059\u308bdotnetcore)<\/ul>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d7e08913a08637a6a1b7c\/9-0.png\" alt=\"\u540d\u79f0\u672a\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb.drawio.png\" \/><\/div>\n<h2>\u6587\u4ef6\u6811\u6458\u5f55 sh\u00f9 l\u00f9)<\/h2>\n<pre class=\"post-pre\"><code>\u251c\u2500\u2500 docker-compose.yml\r\n\u251c\u2500\u2500 dotnet\r\n\u2502   \u251c\u2500\u2500 Dockerfile\r\n\u2502   \u251c\u2500\u2500 docker-entrypoint.sh\r\n\u2502   \u2514\u2500\u2500 src\r\n\u2502       \u251c\u2500\u2500 Domain\r\n\u2502       \u2502   \u251c\u2500\u2500 Domain.csproj\r\n\u2502       \u2502   \u251c\u2500\u2500 EventIdEnum.cs\r\n\u2502       \u2502   \u251c\u2500\u2500 IEventInsert.cs\r\n\u2502       \u2502   \u251c\u2500\u2500 User.cs\r\n\u2502       \u2502   \u251c\u2500\u2500 UserId.cs\r\n\u2502       \u2502   \u251c\u2500\u2500 UserName.cs\r\n\u2502       \u251c\u2500\u2500 Infrastructure\r\n\u2502       \u2502   \u251c\u2500\u2500 DataBase\r\n\u2502       \u2502   \u2502   \u251c\u2500\u2500 Event.cs\r\n\u2502       \u2502   \u2502   \u2514\u2500\u2500 EventstoreContext.cs\r\n\u2502       \u2502   \u251c\u2500\u2500 EventInsert.cs\r\n\u2502       \u2502   \u251c\u2500\u2500 Infrastructure.csproj\r\n\u2502       \u251c\u2500\u2500 Projector\r\n\u2502       \u2502   \u251c\u2500\u2500 Commands.cs\r\n\u2502       \u2502   \u251c\u2500\u2500 DataBase\r\n\u2502       \u2502   \u2502   \u251c\u2500\u2500 SampleDBContext.cs\r\n\u2502       \u2502   \u2502   \u2514\u2500\u2500 User.cs\r\n\u2502       \u2502   \u251c\u2500\u2500 Program.cs\r\n\u2502       \u2502   \u251c\u2500\u2500 Projector.csproj\r\n\u2502       \u2514\u2500\u2500 SampleCmd\r\n\u2502           \u251c\u2500\u2500 Commands.cs\r\n\u2502           \u251c\u2500\u2500 DataBase\r\n\u2502           \u2502   \u251c\u2500\u2500 SampleContext.cs\r\n\u2502           \u2502   \u2514\u2500\u2500 User.cs\r\n\u2502           \u251c\u2500\u2500 Program.cs\r\n\u2502           \u251c\u2500\u2500 SampleCmd.csproj\r\n\u251c\u2500\u2500 read_model\r\n\u2502   \u2514\u2500\u2500 Dockerfile\r\n\u2514\u2500\u2500 write_model\r\n    \u251c\u2500\u2500 Dockerfile\r\n    \u2514\u2500\u2500 initdb\r\n        \u251c\u2500\u2500 eventstore.backup\r\n        \u2514\u2500\u2500 init.sh\r\n<\/code><\/pre>\n<h1>\u9886\u57df\u6216\u4e8b\u4ef6<\/h1>\n<p>\u6682\u65f6\u5c06\u5176\u8bbe\u4e3a\u4e00\u4e2a\u666e\u901a\u7528\u6237\u8868\u8fdb\u884cCRUD\u7684\u9886\u57df\u3002<\/p>\n<h2>\u57df\u540d (yu4 ming2)<\/h2>\n<div><img decoding=\"async\" class=\"post-images\" title=\"undefined\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d7e08913a08637a6a1b7c\/undefined\" alt=\"undefined\" \/><\/div>\n<h2>\u6d3b\u52a8<\/h2>\n<div>\n<div class=\"post-table\">EventId\u540d\u79f0\u8aac\u660e\u30b9\u30ad\u30fc\u30de\u3063\u307d\u3044\u3082\u306e1UserAdded\u30e6\u30fc\u30b6\u30fc\u3092\u8ffd\u52a0\u3059\u308b{ &#8220;type&#8221;: &#8220;object&#8221;, &#8220;properties&#8221;: { &#8220;name&#8221;: { &#8220;type&#8221;: &#8220;string&#8221; } } }2UserEdited\u30e6\u30fc\u30b6\u30fc\u3092\u7de8\u96c6\u3059\u308b{ &#8220;type&#8221;: &#8220;object&#8221;, &#8220;properties&#8221;: { &#8220;id&#8221;: { &#8220;type&#8221;: &#8220;string&#8221; }, &#8220;name&#8221;: { &#8220;type&#8221;: &#8220;string&#8221; } } }3UserDeleted\u30e6\u30fc\u30b6\u30fc\u3092\u524a\u9664\u3059\u308b{ &#8220;type&#8221;: &#8220;object&#8221;, &#8220;properties&#8221;: { &#8220;id&#8221;: { &#8220;type&#8221;: &#8220;string&#8221; } } }<\/div>\n<\/div>\n<h2>ER\u56fe<\/h2>\n<div><img decoding=\"async\" class=\"post-images\" title=\"undefined\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d7e08913a08637a6a1b7c\/undefined\" alt=\"undefined\" \/><\/div>\n<h1>\u8bf7\u63d0\u4f9bProjector\u7684\u6307\u4ee4\u3002<\/h1>\n<p>\u6211\u5df2\u7ecf\u4e3a\u6570\u636e\u5e93\u6062\u590d\u51c6\u5907\u597d\u4e86init\uff0c\u5e76\u4e3a\u4e8b\u4ef6\u8ba2\u9605\u51c6\u5907\u597d\u4e86subscription\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"nv\">$ <\/span>docker <span class=\"nb\">exec<\/span> <span class=\"nt\">-it<\/span> dotnet dotnet run <span class=\"nt\">--project<\/span> \/root\/src\/Projector <span class=\"nb\">help\r\n<\/span>Usage: Projector &lt;Command&gt;\r\n\r\nCommands:\r\n  <span class=\"nb\">help            <\/span>Display help.\r\n  init            \r\n  subscription    \r\n  version         Display version.\r\n<\/code><\/pre>\n<h2>\u6062\u590d\u6570\u636e\u5e93\u65f6\u7528\u5230\u7684init\u5185\u5bb9\u6458\u8981<\/h2>\n<pre class=\"post-pre\"><code>    <span class=\"c1\">\/\/ read_model\u306eSample\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306eDbContext\u3092\u30b3\u30f3\u30b9\u30c8\u30e9\u30af\u30bf\u30a4\u30f3\u30b8\u30a7\u30af\u30b7\u30e7\u30f3\u3057\u3066\u3044\u308b.<\/span>\r\n    <span class=\"k\">private<\/span> <span class=\"n\">SampleDBContext<\/span> <span class=\"n\">Smp<\/span> <span class=\"p\">{<\/span> <span class=\"k\">get<\/span><span class=\"p\">;<\/span> <span class=\"p\">}<\/span>\r\n\r\n    <span class=\"c1\">\/\/ write_model\u306eEventstore\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306eDbContext\u3092\u30b3\u30f3\u30b9\u30c8\u30e9\u30af\u30bf\u30a4\u30f3\u30b8\u30a7\u30af\u30b7\u30e7\u30f3\u3057\u3066\u3044\u308b.<\/span>\r\n    <span class=\"k\">private<\/span> <span class=\"n\">EventstoreContext<\/span> <span class=\"n\">Ev<\/span> <span class=\"p\">{<\/span> <span class=\"k\">get<\/span><span class=\"p\">;<\/span> <span class=\"p\">}<\/span>\r\n\r\n    <span class=\"k\">public<\/span> <span class=\"k\">async<\/span> <span class=\"n\">Task<\/span> <span class=\"nf\">Init<\/span><span class=\"p\">()<\/span>\r\n    <span class=\"p\">{<\/span>\r\n        <span class=\"n\">Smp<\/span><span class=\"p\">.<\/span><span class=\"n\">Database<\/span><span class=\"p\">.<\/span><span class=\"nf\">EnsureDeleted<\/span><span class=\"p\">();<\/span> <span class=\"c1\">\/\/ Sample\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u524a\u9664<\/span>\r\n        <span class=\"n\">Smp<\/span><span class=\"p\">.<\/span><span class=\"n\">Database<\/span><span class=\"p\">.<\/span><span class=\"nf\">EnsureCreated<\/span><span class=\"p\">();<\/span> <span class=\"c1\">\/\/ Sample\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u751f\u6210<\/span>\r\n\r\n        <span class=\"c1\">\/\/ \u30a4\u30d9\u30f3\u30c8\u5206\u518d\u751f<\/span>\r\n        <span class=\"k\">foreach<\/span> <span class=\"p\">(<\/span><span class=\"kt\">var<\/span> <span class=\"n\">x<\/span> <span class=\"k\">in<\/span> <span class=\"n\">Ev<\/span><span class=\"p\">.<\/span><span class=\"n\">Events<\/span><span class=\"p\">)<\/span>\r\n            <span class=\"nf\">Handle<\/span><span class=\"p\">(<\/span><span class=\"n\">x<\/span><span class=\"p\">);<\/span>\r\n    <span class=\"p\">}<\/span>\r\n\r\n    <span class=\"c1\">\/\/ \u30a4\u30d9\u30f3\u30c8id\u6bce\u306b\u51e6\u7406.users\u30c6\u30fc\u30d6\u30eb\u306binsert\u3057\u305f\u308aupdate\u3057\u305f\u308adelete\u3057\u305f\u308a.<\/span>\r\n    <span class=\"k\">private<\/span> <span class=\"k\">void<\/span> <span class=\"nf\">Handle<\/span><span class=\"p\">(<\/span><span class=\"n\">Event<\/span> <span class=\"n\">ev<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"p\">{<\/span>\r\n        <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"n\">Enum<\/span><span class=\"p\">.<\/span><span class=\"nf\">IsDefined<\/span><span class=\"p\">(<\/span><span class=\"k\">typeof<\/span><span class=\"p\">(<\/span><span class=\"n\">EventIdEnum<\/span><span class=\"p\">),<\/span> <span class=\"n\">ev<\/span><span class=\"p\">.<\/span><span class=\"n\">EventId<\/span><span class=\"p\">)<\/span> <span class=\"p\">==<\/span> <span class=\"k\">false<\/span><span class=\"p\">)<\/span>\r\n            <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\r\n\r\n        <span class=\"k\">switch<\/span> <span class=\"p\">((<\/span><span class=\"n\">EventIdEnum<\/span><span class=\"p\">)<\/span><span class=\"n\">ev<\/span><span class=\"p\">.<\/span><span class=\"n\">EventId<\/span><span class=\"p\">)<\/span>\r\n        <span class=\"p\">{<\/span>\r\n            <span class=\"k\">case<\/span> <span class=\"n\">EventIdEnum<\/span><span class=\"p\">.<\/span><span class=\"n\">UserAdded<\/span><span class=\"p\">:<\/span> <span class=\"nf\">UserUpsertHandler<\/span><span class=\"p\">(<\/span><span class=\"n\">ev<\/span><span class=\"p\">.<\/span><span class=\"n\">Data<\/span><span class=\"p\">.<\/span><span class=\"n\">RootElement<\/span><span class=\"p\">);<\/span> <span class=\"k\">break<\/span><span class=\"p\">;<\/span>\r\n            <span class=\"k\">case<\/span> <span class=\"n\">EventIdEnum<\/span><span class=\"p\">.<\/span><span class=\"n\">UserEdited<\/span><span class=\"p\">:<\/span> <span class=\"nf\">UserUpsertHandler<\/span><span class=\"p\">(<\/span><span class=\"n\">ev<\/span><span class=\"p\">.<\/span><span class=\"n\">Data<\/span><span class=\"p\">.<\/span><span class=\"n\">RootElement<\/span><span class=\"p\">);<\/span> <span class=\"k\">break<\/span><span class=\"p\">;<\/span>\r\n            <span class=\"k\">case<\/span> <span class=\"n\">EventIdEnum<\/span><span class=\"p\">.<\/span><span class=\"n\">UserDeleted<\/span><span class=\"p\">:<\/span> <span class=\"nf\">UserDeleteHandler<\/span><span class=\"p\">(<\/span><span class=\"n\">ev<\/span><span class=\"p\">.<\/span><span class=\"n\">Data<\/span><span class=\"p\">.<\/span><span class=\"n\">RootElement<\/span><span class=\"p\">);<\/span> <span class=\"k\">break<\/span><span class=\"p\">;<\/span>\r\n            <span class=\"k\">default<\/span><span class=\"p\">:<\/span> <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"nf\">ArgumentException<\/span><span class=\"p\">(<\/span><span class=\"s\">$\"not implemented. <\/span><span class=\"p\">{<\/span><span class=\"n\">ev<\/span><span class=\"p\">.<\/span><span class=\"n\">EventId<\/span><span class=\"p\">}<\/span><span class=\"s\">\"<\/span><span class=\"p\">);<\/span>\r\n        <span class=\"p\">};<\/span>\r\n    <span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<h2>\u8ba2\u9605\u6d3b\u52a8\u5185\u5bb9\u6458\u8981<\/h2>\n<pre class=\"post-pre\"><code>    <span class=\"k\">public<\/span> <span class=\"k\">async<\/span> <span class=\"n\">Task<\/span> <span class=\"nf\">Subscription<\/span><span class=\"p\">(<\/span><span class=\"n\">EventstoreContext<\/span> <span class=\"n\">ev<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"p\">{<\/span>\r\n        <span class=\"kt\">var<\/span> <span class=\"n\">conn<\/span> <span class=\"p\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">NpgsqlConnection<\/span><span class=\"p\">)<\/span><span class=\"n\">ev<\/span><span class=\"p\">.<\/span><span class=\"n\">Database<\/span><span class=\"p\">.<\/span><span class=\"nf\">GetDbConnection<\/span><span class=\"p\">();<\/span>\r\n        <span class=\"n\">conn<\/span><span class=\"p\">.<\/span><span class=\"nf\">Open<\/span><span class=\"p\">();<\/span>\r\n\r\n        <span class=\"k\">try<\/span>\r\n        <span class=\"p\">{<\/span>\r\n            <span class=\"n\">conn<\/span><span class=\"p\">.<\/span><span class=\"n\">Notification<\/span> <span class=\"p\">+=<\/span> <span class=\"n\">OnNotification<\/span><span class=\"p\">;<\/span> \r\n\r\n            <span class=\"c1\">\/\/ postgresql\u306eLISTEN\u3067\u8cfc\u8aad\u3059\u308b.<\/span>\r\n            <span class=\"k\">using<\/span> <span class=\"nn\">var<\/span> <span class=\"n\">cmd<\/span> <span class=\"p\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nf\">NpgsqlCommand<\/span><span class=\"p\">(<\/span><span class=\"s\">\"LISTEN event_channel\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">conn<\/span><span class=\"p\">);<\/span>\r\n            <span class=\"n\">cmd<\/span><span class=\"p\">.<\/span><span class=\"nf\">ExecuteNonQuery<\/span><span class=\"p\">();<\/span>\r\n\r\n            <span class=\"k\">while<\/span> <span class=\"p\">(<\/span><span class=\"n\">Context<\/span><span class=\"p\">.<\/span><span class=\"n\">CancellationToken<\/span><span class=\"p\">.<\/span><span class=\"n\">IsCancellationRequested<\/span> <span class=\"p\">==<\/span> <span class=\"k\">false<\/span><span class=\"p\">)<\/span>\r\n                <span class=\"k\">await<\/span> <span class=\"n\">conn<\/span><span class=\"p\">.<\/span><span class=\"nf\">WaitAsync<\/span><span class=\"p\">(<\/span><span class=\"n\">Context<\/span><span class=\"p\">.<\/span><span class=\"n\">CancellationToken<\/span><span class=\"p\">);<\/span>\r\n        <span class=\"p\">}<\/span>\r\n        <span class=\"k\">catch<\/span> <span class=\"p\">(<\/span><span class=\"n\">Exception<\/span> <span class=\"n\">ex<\/span><span class=\"p\">)<\/span> <span class=\"k\">when<\/span> <span class=\"p\">(!(<\/span><span class=\"n\">ex<\/span> <span class=\"k\">is<\/span> <span class=\"n\">OperationCanceledException<\/span><span class=\"p\">))<\/span>\r\n        <span class=\"p\">{<\/span>\r\n            <span class=\"n\">Console<\/span><span class=\"p\">.<\/span><span class=\"nf\">WriteLine<\/span><span class=\"p\">(<\/span><span class=\"n\">ex<\/span><span class=\"p\">.<\/span><span class=\"nf\">ToString<\/span><span class=\"p\">());<\/span>\r\n        <span class=\"p\">}<\/span>\r\n        <span class=\"k\">finally<\/span>\r\n        <span class=\"p\">{<\/span>\r\n            <span class=\"n\">conn<\/span><span class=\"p\">.<\/span><span class=\"nf\">Close<\/span><span class=\"p\">();<\/span>\r\n        <span class=\"p\">}<\/span>\r\n    <span class=\"p\">}<\/span>\r\n\r\n    <span class=\"c1\">\/\/ \u30a4\u30d9\u30f3\u30c8\u304c\u767a\u884c\u3055\u308c\u308b\u5ea6\u306b\u51e6\u7406.<\/span>\r\n    <span class=\"k\">private<\/span> <span class=\"k\">void<\/span> <span class=\"nf\">OnNotification<\/span><span class=\"p\">(<\/span><span class=\"kt\">object<\/span> <span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">NpgsqlNotificationEventArgs<\/span> <span class=\"n\">e<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"p\">{<\/span>\r\n        <span class=\"n\">Console<\/span><span class=\"p\">.<\/span><span class=\"nf\">WriteLine<\/span><span class=\"p\">(<\/span><span class=\"s\">\"event handled: \"<\/span> <span class=\"p\">+<\/span> <span class=\"n\">e<\/span><span class=\"p\">.<\/span><span class=\"n\">Payload<\/span><span class=\"p\">);<\/span>\r\n        <span class=\"n\">Event<\/span><span class=\"p\">?<\/span> <span class=\"n\">ev<\/span> <span class=\"p\">=<\/span> <span class=\"n\">JsonSerializer<\/span><span class=\"p\">.<\/span><span class=\"n\">Deserialize<\/span><span class=\"p\">&lt;<\/span><span class=\"n\">Event<\/span><span class=\"p\">&gt;(<\/span><span class=\"n\">e<\/span><span class=\"p\">.<\/span><span class=\"n\">Payload<\/span><span class=\"p\">,<\/span> <span class=\"k\">new<\/span> <span class=\"n\">JsonSerializerOptions<\/span> \r\n        <span class=\"p\">{<\/span>\r\n            <span class=\"n\">PropertyNameCaseInsensitive<\/span> <span class=\"p\">=<\/span> <span class=\"k\">true<\/span><span class=\"p\">,<\/span>\r\n        <span class=\"p\">});<\/span>\r\n\r\n        <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"n\">ev<\/span> <span class=\"k\">is<\/span> <span class=\"k\">not<\/span> <span class=\"k\">null<\/span><span class=\"p\">)<\/span>\r\n            <span class=\"nf\">Handle<\/span><span class=\"p\">(<\/span><span class=\"n\">ev<\/span><span class=\"p\">);<\/span>\r\n    <span class=\"p\">}<\/span>\r\n<\/code><\/pre>\n<h1>Eventstore\u6570\u636e\u5e93\u7684\u89e6\u53d1\u5668\u90e8\u5206\u3002<\/h1>\n<p>\u5c06\u6570\u636e\u52a0\u8f7d\u5230write_model\u7684\u6570\u636e\u5e93\u4e2d\u3002<\/p>\n<p>\u89e6\u53d1\u6761\u4ef6\uff1a\u5728events\u8868\u4e2d\u8fdb\u884c\u63d2\u5165<br \/>\n\u6267\u884c\u5185\u5bb9\uff1a\u901a\u77e5\u63d2\u5165\u7684\u5185\u5bb9<\/p>\n<pre class=\"post-pre\"><code><span class=\"k\">CREATE<\/span> <span class=\"k\">OR<\/span> <span class=\"k\">REPLACE<\/span> <span class=\"k\">FUNCTION<\/span> <span class=\"k\">public<\/span><span class=\"p\">.<\/span><span class=\"n\">event_insert_trigger<\/span><span class=\"p\">()<\/span>\r\n    <span class=\"k\">RETURNS<\/span> <span class=\"k\">trigger<\/span>\r\n    <span class=\"k\">LANGUAGE<\/span> <span class=\"s1\">'plpgsql'<\/span>\r\n    <span class=\"n\">COST<\/span> <span class=\"mi\">100<\/span>\r\n    <span class=\"k\">VOLATILE<\/span> <span class=\"k\">NOT<\/span> <span class=\"n\">LEAKPROOF<\/span>\r\n<span class=\"k\">AS<\/span> <span class=\"err\">$<\/span><span class=\"n\">BODY<\/span><span class=\"err\">$<\/span>\r\n<span class=\"k\">BEGIN<\/span>\r\n<span class=\"n\">PERFORM<\/span> <span class=\"n\">pg_notify<\/span><span class=\"p\">(<\/span>\r\n\t<span class=\"s1\">'event_channel'<\/span><span class=\"p\">,<\/span>\r\n\t<span class=\"n\">row_to_json<\/span><span class=\"p\">(<\/span><span class=\"k\">NEW<\/span><span class=\"p\">)::<\/span><span class=\"nb\">text<\/span>\r\n<span class=\"p\">);<\/span>\r\n\r\n<span class=\"k\">return<\/span> <span class=\"k\">NULL<\/span><span class=\"p\">;<\/span>\r\n<span class=\"k\">END<\/span>\r\n<span class=\"err\">$<\/span><span class=\"n\">BODY<\/span><span class=\"err\">$<\/span><span class=\"p\">;<\/span>\r\n\r\n<span class=\"k\">ALTER<\/span> <span class=\"k\">FUNCTION<\/span> <span class=\"k\">public<\/span><span class=\"p\">.<\/span><span class=\"n\">event_insert_trigger<\/span><span class=\"p\">()<\/span>\r\n    <span class=\"k\">OWNER<\/span> <span class=\"k\">TO<\/span> <span class=\"n\">postgres<\/span><span class=\"p\">;<\/span>\r\n\r\n<span class=\"k\">CREATE<\/span> <span class=\"k\">TRIGGER<\/span> <span class=\"n\">event_trigger<\/span>\r\n    <span class=\"k\">AFTER<\/span> <span class=\"k\">INSERT<\/span>\r\n    <span class=\"k\">ON<\/span> <span class=\"k\">public<\/span><span class=\"p\">.<\/span><span class=\"n\">events<\/span>\r\n    <span class=\"k\">FOR<\/span> <span class=\"k\">EACH<\/span> <span class=\"k\">ROW<\/span>\r\n    <span class=\"k\">EXECUTE<\/span> <span class=\"k\">FUNCTION<\/span> <span class=\"k\">public<\/span><span class=\"p\">.<\/span><span class=\"n\">event_insert_trigger<\/span><span class=\"p\">();<\/span>\r\n<\/code><\/pre>\n<h1>\u6837\u672c\u547d\u4ee4\uff08SampleCmd\uff09\u7684\u6307\u4ee4<\/h1>\n<p>\u6682\u65f6\u4f7f\u7528\u63a7\u5236\u53f0\u5e94\u7528\u7a0b\u5e8f\u3002\u4f7f\u7528\u547d\u4ee4\u5982add\u6216edit\uff0c\u6307\u5b9a\u4e8b\u4ef6\u540d\u79f0\u5e76\u9644\u5e26\u5fc5\u8981\u7684\u53c2\u6570\u5c06\u4e8b\u4ef6\u63d2\u5165write_model\u4e2d\u3002<\/p>\n<pre class=\"post-pre\"><code><span class=\"nv\">$ <\/span>docker <span class=\"nb\">exec<\/span> <span class=\"nt\">-it<\/span> dotnet dotnet run <span class=\"nt\">--project<\/span> \/root\/src\/SampleCmd <span class=\"nb\">help\r\n<\/span>Usage: SampleCmd <span class=\"o\">[<\/span>options...]\r\n\r\nOptions:\r\n  <span class=\"nt\">-e<\/span>, <span class=\"nt\">--eventname<\/span> &lt;String&gt;    event name. add or edit or delete <span class=\"o\">(<\/span>Required<span class=\"o\">)<\/span>\r\n  <span class=\"nt\">-n<\/span>, <span class=\"nt\">--username<\/span> &lt;String&gt;     user name. Required <span class=\"k\">for <\/span>add or edit <span class=\"o\">(<\/span>Default: null<span class=\"o\">)<\/span>\r\n  <span class=\"nt\">-id<\/span>, <span class=\"nt\">--id<\/span> &lt;String&gt;          guid. Required <span class=\"k\">for <\/span>edit or delete <span class=\"o\">(<\/span>Default: null<span class=\"o\">)<\/span>\r\n\r\nCommands:\r\n  <span class=\"nb\">help       <\/span>Display help.\r\n  version    Display version.\r\n<\/code><\/pre>\n<h1>\u603b\u7ed3\u3002<\/h1>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d7e08913a08637a6a1b7c\/35-0.png\" alt=\"index.png\" \/><\/div>\n<p>\u5982\u679c\u6211\u4eec\u5c06\u4e00\u4e2aPostgreSQL\u6570\u636e\u5e93\u62c6\u5206\u6210\u591a\u4e2a\u6a21\u5f0f\u6765\u7ba1\u7406\uff0c\u53ef\u80fd\u4e5f\u662f\u4e00\u4e2a\u4e0d\u9519\u7684\u9009\u62e9\u3002<\/p>\n<div><img decoding=\"async\" class=\"post-images\" title=\"\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d7e08913a08637a6a1b7c\/37-0.png\" alt=\"index.png\" \/><\/div>\n<p>\u5728\u4e8b\u4ef6\u53d1\u751f\u65f6\u6267\u884cProjector\u4f5c\u4e3a\u5916\u90e8\u5e94\u7528\u7a0b\u5e8f\u4f3c\u4e4e\u4e5f\u662f\u4e00\u4e2a\u53ef\u884c\u7684\u9009\u62e9\u3002\u5728\u8fd9\u79cd\u6a21\u5f0f\u4e2d\uff0c\u6062\u590dread_model\u65f6\u9700\u8981\u4f7f\u7528write_model\u7684\u4fe1\u606f\u3002<\/p>\n<p>\u8bf7\u95ee\u5728\u4f7f\u7528CQRS+\u4e8b\u4ef6\u6eaf\u6e90\u5728\u79c1\u6709\u4e91\u4e2d\u8fdb\u884c\u5b9e\u73b0\u65f6\uff0c\u662f\u5426\u6709\u4efb\u4f55\u65b9\u4fbf\u7684\u673a\u5236\u53ef\u4ee5\u6559\u6388\uff1f<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u7ecf\u8fc7 \u5f53\u8bd5\u56fe\u5728\u672c\u5730\u73af\u5883\u4e2d\u5b9e\u73b0CQRS+\u4e8b\u4ef6\u6eaf\u6e90\u65f6\uff0c\u6211\u8003\u8651\u5230\u662f\u5426\u53ef\u4ee5\u5728\u4e0d\u4f7f\u7528Apache Kafka\u7b49\u6d88\u606f\u961f\u5217\u7684 [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-47323","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v21.5 (Yoast SEO v21.5) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>\u4ee5\u4e0b\u662f\u5c0f\u578b\u5e94\u7528\u7a0b\u5e8f\u4e2dCQRS+\u4e8b\u4ef6\u6eaf\u6e90\u7684\u914d\u7f6e\u793a\u4f8b\uff1a - Blog - Silicon Cloud<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.silicloud.com\/zh\/blog\/\u4ee5\u4e0b\u662f\u5c0f\u578b\u5e94\u7528\u7a0b\u5e8f\u4e2dcqrs\u4e8b\u4ef6\u6eaf\u6e90\u7684\u914d\u7f6e\u793a\u4f8b\uff1a\/\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"\u4ee5\u4e0b\u662f\u5c0f\u578b\u5e94\u7528\u7a0b\u5e8f\u4e2dCQRS+\u4e8b\u4ef6\u6eaf\u6e90\u7684\u914d\u7f6e\u793a\u4f8b\uff1a\" \/>\n<meta property=\"og:description\" content=\"\u7ecf\u8fc7 \u5f53\u8bd5\u56fe\u5728\u672c\u5730\u73af\u5883\u4e2d\u5b9e\u73b0CQRS+\u4e8b\u4ef6\u6eaf\u6e90\u65f6\uff0c\u6211\u8003\u8651\u5230\u662f\u5426\u53ef\u4ee5\u5728\u4e0d\u4f7f\u7528Apache Kafka\u7b49\u6d88\u606f\u961f\u5217\u7684 [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.silicloud.com\/zh\/blog\/\u4ee5\u4e0b\u662f\u5c0f\u578b\u5e94\u7528\u7a0b\u5e8f\u4e2dcqrs\u4e8b\u4ef6\u6eaf\u6e90\u7684\u914d\u7f6e\u793a\u4f8b\uff1a\/\" \/>\n<meta property=\"og:site_name\" content=\"Blog - Silicon Cloud\" \/>\n<meta property=\"article:published_time\" content=\"2023-11-07T05:27:38+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-04-29T02:09:35+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d7e08913a08637a6a1b7c\/9-0.png\" \/>\n<meta name=\"author\" content=\"\u79d1, \u96c5\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"\u79d1, \u96c5\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"2 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bb%a5%e4%b8%8b%e6%98%af%e5%b0%8f%e5%9e%8b%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e4%b8%adcqrs%e4%ba%8b%e4%bb%b6%e6%ba%af%e6%ba%90%e7%9a%84%e9%85%8d%e7%bd%ae%e7%a4%ba%e4%be%8b%ef%bc%9a\/\",\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bb%a5%e4%b8%8b%e6%98%af%e5%b0%8f%e5%9e%8b%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e4%b8%adcqrs%e4%ba%8b%e4%bb%b6%e6%ba%af%e6%ba%90%e7%9a%84%e9%85%8d%e7%bd%ae%e7%a4%ba%e4%be%8b%ef%bc%9a\/\",\"name\":\"\u4ee5\u4e0b\u662f\u5c0f\u578b\u5e94\u7528\u7a0b\u5e8f\u4e2dCQRS+\u4e8b\u4ef6\u6eaf\u6e90\u7684\u914d\u7f6e\u793a\u4f8b\uff1a - Blog - Silicon Cloud\",\"isPartOf\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#website\"},\"datePublished\":\"2023-11-07T05:27:38+00:00\",\"dateModified\":\"2024-04-29T02:09:35+00:00\",\"author\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/41e222757cdd2a3365361328bd79970a\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bb%a5%e4%b8%8b%e6%98%af%e5%b0%8f%e5%9e%8b%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e4%b8%adcqrs%e4%ba%8b%e4%bb%b6%e6%ba%af%e6%ba%90%e7%9a%84%e9%85%8d%e7%bd%ae%e7%a4%ba%e4%be%8b%ef%bc%9a\/#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bb%a5%e4%b8%8b%e6%98%af%e5%b0%8f%e5%9e%8b%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e4%b8%adcqrs%e4%ba%8b%e4%bb%b6%e6%ba%af%e6%ba%90%e7%9a%84%e9%85%8d%e7%bd%ae%e7%a4%ba%e4%be%8b%ef%bc%9a\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bb%a5%e4%b8%8b%e6%98%af%e5%b0%8f%e5%9e%8b%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e4%b8%adcqrs%e4%ba%8b%e4%bb%b6%e6%ba%af%e6%ba%90%e7%9a%84%e9%85%8d%e7%bd%ae%e7%a4%ba%e4%be%8b%ef%bc%9a\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.silicloud.com\/zh\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"\u4ee5\u4e0b\u662f\u5c0f\u578b\u5e94\u7528\u7a0b\u5e8f\u4e2dCQRS+\u4e8b\u4ef6\u6eaf\u6e90\u7684\u914d\u7f6e\u793a\u4f8b\uff1a\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#website\",\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/\",\"name\":\"Blog - Silicon Cloud\",\"description\":\"\",\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/41e222757cdd2a3365361328bd79970a\",\"name\":\"\u79d1, \u96c5\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/1b2d3e00a7df03689797ebd4af8c5827ba5af936849a71050ec331f4cf902c5d?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/1b2d3e00a7df03689797ebd4af8c5827ba5af936849a71050ec331f4cf902c5d?s=96&d=mm&r=g\",\"caption\":\"\u79d1, \u96c5\"},\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/author\/keya\/\"},{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bb%a5%e4%b8%8b%e6%98%af%e5%b0%8f%e5%9e%8b%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e4%b8%adcqrs%e4%ba%8b%e4%bb%b6%e6%ba%af%e6%ba%90%e7%9a%84%e9%85%8d%e7%bd%ae%e7%a4%ba%e4%be%8b%ef%bc%9a\/#local-main-organization-logo\",\"url\":\"\",\"contentUrl\":\"\",\"caption\":\"Blog - Silicon Cloud\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"\u4ee5\u4e0b\u662f\u5c0f\u578b\u5e94\u7528\u7a0b\u5e8f\u4e2dCQRS+\u4e8b\u4ef6\u6eaf\u6e90\u7684\u914d\u7f6e\u793a\u4f8b\uff1a - Blog - Silicon Cloud","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.silicloud.com\/zh\/blog\/\u4ee5\u4e0b\u662f\u5c0f\u578b\u5e94\u7528\u7a0b\u5e8f\u4e2dcqrs\u4e8b\u4ef6\u6eaf\u6e90\u7684\u914d\u7f6e\u793a\u4f8b\uff1a\/","og_locale":"zh_CN","og_type":"article","og_title":"\u4ee5\u4e0b\u662f\u5c0f\u578b\u5e94\u7528\u7a0b\u5e8f\u4e2dCQRS+\u4e8b\u4ef6\u6eaf\u6e90\u7684\u914d\u7f6e\u793a\u4f8b\uff1a","og_description":"\u7ecf\u8fc7 \u5f53\u8bd5\u56fe\u5728\u672c\u5730\u73af\u5883\u4e2d\u5b9e\u73b0CQRS+\u4e8b\u4ef6\u6eaf\u6e90\u65f6\uff0c\u6211\u8003\u8651\u5230\u662f\u5426\u53ef\u4ee5\u5728\u4e0d\u4f7f\u7528Apache Kafka\u7b49\u6d88\u606f\u961f\u5217\u7684 [&hellip;]","og_url":"https:\/\/www.silicloud.com\/zh\/blog\/\u4ee5\u4e0b\u662f\u5c0f\u578b\u5e94\u7528\u7a0b\u5e8f\u4e2dcqrs\u4e8b\u4ef6\u6eaf\u6e90\u7684\u914d\u7f6e\u793a\u4f8b\uff1a\/","og_site_name":"Blog - Silicon Cloud","article_published_time":"2023-11-07T05:27:38+00:00","article_modified_time":"2024-04-29T02:09:35+00:00","og_image":[{"url":"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/657d7e08913a08637a6a1b7c\/9-0.png"}],"author":"\u79d1, \u96c5","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"\u79d1, \u96c5","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"2 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bb%a5%e4%b8%8b%e6%98%af%e5%b0%8f%e5%9e%8b%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e4%b8%adcqrs%e4%ba%8b%e4%bb%b6%e6%ba%af%e6%ba%90%e7%9a%84%e9%85%8d%e7%bd%ae%e7%a4%ba%e4%be%8b%ef%bc%9a\/","url":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bb%a5%e4%b8%8b%e6%98%af%e5%b0%8f%e5%9e%8b%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e4%b8%adcqrs%e4%ba%8b%e4%bb%b6%e6%ba%af%e6%ba%90%e7%9a%84%e9%85%8d%e7%bd%ae%e7%a4%ba%e4%be%8b%ef%bc%9a\/","name":"\u4ee5\u4e0b\u662f\u5c0f\u578b\u5e94\u7528\u7a0b\u5e8f\u4e2dCQRS+\u4e8b\u4ef6\u6eaf\u6e90\u7684\u914d\u7f6e\u793a\u4f8b\uff1a - Blog - Silicon Cloud","isPartOf":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/#website"},"datePublished":"2023-11-07T05:27:38+00:00","dateModified":"2024-04-29T02:09:35+00:00","author":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/41e222757cdd2a3365361328bd79970a"},"breadcrumb":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bb%a5%e4%b8%8b%e6%98%af%e5%b0%8f%e5%9e%8b%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e4%b8%adcqrs%e4%ba%8b%e4%bb%b6%e6%ba%af%e6%ba%90%e7%9a%84%e9%85%8d%e7%bd%ae%e7%a4%ba%e4%be%8b%ef%bc%9a\/#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.silicloud.com\/zh\/blog\/%e4%bb%a5%e4%b8%8b%e6%98%af%e5%b0%8f%e5%9e%8b%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e4%b8%adcqrs%e4%ba%8b%e4%bb%b6%e6%ba%af%e6%ba%90%e7%9a%84%e9%85%8d%e7%bd%ae%e7%a4%ba%e4%be%8b%ef%bc%9a\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bb%a5%e4%b8%8b%e6%98%af%e5%b0%8f%e5%9e%8b%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e4%b8%adcqrs%e4%ba%8b%e4%bb%b6%e6%ba%af%e6%ba%90%e7%9a%84%e9%85%8d%e7%bd%ae%e7%a4%ba%e4%be%8b%ef%bc%9a\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.silicloud.com\/zh\/blog\/"},{"@type":"ListItem","position":2,"name":"\u4ee5\u4e0b\u662f\u5c0f\u578b\u5e94\u7528\u7a0b\u5e8f\u4e2dCQRS+\u4e8b\u4ef6\u6eaf\u6e90\u7684\u914d\u7f6e\u793a\u4f8b\uff1a"}]},{"@type":"WebSite","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#website","url":"https:\/\/www.silicloud.com\/zh\/blog\/","name":"Blog - Silicon Cloud","description":"","inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/41e222757cdd2a3365361328bd79970a","name":"\u79d1, \u96c5","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/1b2d3e00a7df03689797ebd4af8c5827ba5af936849a71050ec331f4cf902c5d?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1b2d3e00a7df03689797ebd4af8c5827ba5af936849a71050ec331f4cf902c5d?s=96&d=mm&r=g","caption":"\u79d1, \u96c5"},"url":"https:\/\/www.silicloud.com\/zh\/blog\/author\/keya\/"},{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.silicloud.com\/zh\/blog\/%e4%bb%a5%e4%b8%8b%e6%98%af%e5%b0%8f%e5%9e%8b%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e4%b8%adcqrs%e4%ba%8b%e4%bb%b6%e6%ba%af%e6%ba%90%e7%9a%84%e9%85%8d%e7%bd%ae%e7%a4%ba%e4%be%8b%ef%bc%9a\/#local-main-organization-logo","url":"","contentUrl":"","caption":"Blog - Silicon Cloud"}]}},"_links":{"self":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/47323","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/comments?post=47323"}],"version-history":[{"count":2,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/47323\/revisions"}],"predecessor-version":[{"id":84637,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/47323\/revisions\/84637"}],"wp:attachment":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/media?parent=47323"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/categories?post=47323"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/tags?post=47323"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}