{"id":13618,"date":"2022-08-02T09:46:48","date_gmt":"2022-08-02T16:46:48","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=13618"},"modified":"2025-06-13T20:56:42","modified_gmt":"2025-06-14T03:56:42","slug":"asp-net-crud-nosql-part-5","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/ko\/asp-net-crud-nosql-part-5\/","title":{"rendered":"NoSQL\uc744 \uc0ac\uc6a9\ud55c ASP.NET Core CRUD: 5\ubd80"},"content":{"rendered":"<p><span style=\"font-weight: 400;\">This ASP.NET Core CRUD series is coming to end. We\u2019ve covered <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-with-nosql-part-1\/\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">setup (part 1)<\/span><\/a><span style=\"font-weight: 400;\">, <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/asp-net-crud-nosql-part-2\/\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">reading with SQL++ (part 2)<\/span><\/a><span style=\"font-weight: 400;\">, <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-3\/\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">reading with key-value (part 3)<\/span><\/a><span style=\"font-weight: 400;\">, and <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/asp-net-core-crud-nosql-part-4\/\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">creating\/updating (part 4)<\/span><\/a><span style=\"font-weight: 400;\">. In this last post, we\u2019ll look at the <strong>D<\/strong> in <strong>CRUD<\/strong>: <em>deleting<\/em>.<\/span><\/p>\n<h2><b>Deleting with SQL++ or Key-Value<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Hopefully you\u2019re noticing a pattern. Just as with reading, creating, and updating, you\u2019ve got multiple paths for deleting. You can use a SQL++ <\/span><em><span style=\"font-weight: 400;\">DELETE<\/span><\/em><span style=\"font-weight: 400;\"> statement:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:default decode:true\">DELETE FROM demo._default.wishlist w\r\nWHERE META(w).id = \"1c3de2e7-70ea-4ee2-803b-425bbf6251cb\"<\/pre>\n<p><span style=\"font-weight: 400;\">Or you can use a key-value delete operation (aka &#8220;<em>Remove<\/em>&#8220;):<\/span><\/p>\n<pre class=\"decode-attributes:false lang:default decode:true \">await collection.RemoveAsync(\"1c3de2e7-70ea-4ee2-803b-425bbf6251cb\");<\/pre>\n<p><span style=\"font-weight: 400;\">And as before, here are the very similar guidelines to help you decide which one to use:<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td><strong>Use case<\/strong><\/td>\n<td><strong>Key-value?<\/strong><\/td>\n<td><strong>Why or why not?<\/strong><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">Delete a user with key &#8220;73892&#8221;<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Yes<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Direct access<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">Delete a group of users with keys &#8220;73892&#8221;, &#8220;47212&#8221;, and &#8220;90491&#8221;<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Yes<\/span><\/td>\n<td><span style=\"font-weight: 400;\">This may require multiple key-value operations, but this still may be faster than using a SQL <\/span><em><span style=\"font-weight: 400;\">DELETE \u2026\u200b WHERE \u2026\u200b IN<\/span><\/em><span style=\"font-weight: 400;\"> query.<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">Delete every user from &#8220;Ohio&#8221;<\/span><\/td>\n<td><span style=\"font-weight: 400;\">No<\/span><\/td>\n<td><span style=\"font-weight: 400;\">User\u2019s state is likely a &#8220;secondary&#8221; attribute, not a key (multiple users can be from Ohio). This is a good use case for a SQL++ <\/span><span style=\"font-weight: 400;\">DELETE<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2><b>A Delete endpoint for ASP.NET Core<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">With that in mind, create a delete endpoint like so:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:default decode:true \">[HttpDelete]\r\n[Route(\"api\/delete\")]\r\npublic async Task&lt;IActionResult&gt; Delete(Guid id)\r\n{\r\n\u00a0 \u00a0 var bucket = await _bucketProvider.GetBucketAsync(\"demo\");\r\n\u00a0 \u00a0 var collection = await bucket.CollectionAsync(\"wishlist\");\r\n\r\n\u00a0 \u00a0 await collection.RemoveAsync(id.ToString());\r\n\r\n\u00a0 \u00a0 return Ok(new { success = true });\r\n}<\/pre>\n<p><span style=\"font-weight: 400;\">Try this endpoint with OpenAPI \/ Swagger, and it will behave how you\u2019d expect.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13620\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/08\/delete-endpoint-couchbase-asp-net-api.png\" alt=\"Swagger API view of Couchbase ASP.NET endpoints\" width=\"828\" height=\"745\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/delete-endpoint-couchbase-asp-net-api.png 828w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/delete-endpoint-couchbase-asp-net-api-300x270.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/delete-endpoint-couchbase-asp-net-api-768x691.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/delete-endpoint-couchbase-asp-net-api-20x18.png 20w\" sizes=\"auto, (max-width: 828px) 100vw, 828px\" \/><\/p>\n<h2><b>Should I really delete?<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">In many use cases, you may not want to <\/span><b>actually<\/b><span style=\"font-weight: 400;\"> delete data. You may want to do something called a &#8220;soft&#8221; delete. This involves moving or marking the data in such a way that it still exists in the database, but it is no longer shown to the end user. This has the benefit of being discoverable, recoverable, and reportable.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">It\u2019s also a great opportunity to show the flexibility of a JSON NoSQL database.<\/span><\/p>\n<h2><b>Soft-deleting<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Let\u2019s introduce a &#8220;deleted&#8221; field to wishlist items. This field will contain a date\/time that the item was deleted. If this field exists, the rest of the endpoint should consider this item to be deleted. However, if we need to, we can still query it, report on it, and recover it.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">In a relational database, this would likely require an <\/span><em><span style=\"font-weight: 400;\">ALTER<\/span><\/em><span style=\"font-weight: 400;\">. Depending on the size of your data, it could require some downtime, or possibly a lot of NULL values. In a JSON database, we don\u2019t need to tell the database anything about a new field.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Let\u2019s use the <\/span><a href=\"https:\/\/docs.couchbase.com\/dotnet-sdk\/current\/howtos\/subdocument-operations.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">subdocument API<\/span><\/a><span style=\"font-weight: 400;\"> to add a &#8220;<em>deleted<\/em>&#8221; field to the document. Sub-document means that we will only operate on a <\/span><b>portion<\/b><span style=\"font-weight: 400;\"> of the JSON, and leave the rest alone.<\/span><\/p>\n<pre class=\"decode-attributes:false lang:default decode:true \">[HttpDelete]\r\n[Route(\"api\/softDelete\")]\r\npublic async Task&lt;IActionResult&gt; SoftDelete(Guid id)\r\n{\r\n\u00a0 \u00a0 var bucket = await _bucketProvider.GetBucketAsync(\"demo\");\r\n\u00a0 \u00a0 var collection = await bucket.CollectionAsync(\"wishlist\");\r\n\r\n\u00a0 \u00a0 await collection.MutateInAsync(id.ToString(),\r\n\u00a0 \u00a0 \u00a0 \u00a0 options =&gt; options.Upsert(\"deleted\", DateTime.Now));\r\n\r\n\u00a0 \u00a0 return Ok(new { success = true });\r\n}<\/pre>\n<p><span style=\"font-weight: 400;\">(Make sure <\/span><span style=\"font-weight: 400;\">using <em>Couchbase.KeyValue;<\/em><\/span><span style=\"font-weight: 400;\"> is at the top of your <em>GiftsController<\/em> file.)<\/span><\/p>\n<p><span style=\"font-weight: 400;\">This code sends a command to Couchbase: <\/span><span style=\"font-weight: 400;\">for the document with such-and-such ID, upsert a field called &#8220;<em>deleted<\/em>&#8221; and give it the current date\/time as a value<\/span><span style=\"font-weight: 400;\">.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Notice that with sub-document, we didn\u2019t have to first load the existing document, and we didn\u2019t have to send the entire modified document back over the wire.<\/span><\/p>\n<h2><b>Soft-deleted data<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">The end result will be a document that looks like this:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:js decode:true \">{\r\n\u00a0 \"name\": \"Digital Photo Frame\",\r\n\u00a0 \"deleted\": \"2022-04-21T11:05:26.1766248-04:00\"\r\n}<\/pre>\n<p><span style=\"font-weight: 400;\">The other documents in my wishlist do <\/span><b>not<\/b><span style=\"font-weight: 400;\"> have a <\/span><span style=\"font-weight: 400;\">deleted<\/span><span style=\"font-weight: 400;\"> field. They still look like:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:js decode:true \">{\r\n\u00a0 \"name\": \"Skyline Chili 2XL T-Shirt\"\r\n}<\/pre>\n<p><span style=\"font-weight: 400;\">and<\/span><\/p>\n<pre class=\"decode-attributes:false lang:js decode:true \">{\r\n\u00a0 \"name\": \"Joey Votto jersey\"\r\n}<\/pre>\n<p><span style=\"font-weight: 400;\">Note that they don\u2019t have a <\/span><em><span style=\"font-weight: 400;\">&#8220;deleted&#8221;: null<\/span><\/em><span style=\"font-weight: 400;\"> field; they don\u2019t have a <\/span><span style=\"font-weight: 400;\">&#8220;<em>deleted<\/em>&#8220;<\/span><span style=\"font-weight: 400;\"> field at all.<\/span><\/p>\n<h2><b>Soft-deleted SELECT<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">The data is <\/span><b>marked<\/b><span style=\"font-weight: 400;\"> as deleted, but it\u2019s still in the database. We need to modify the <\/span><em><span style=\"font-weight: 400;\">GetAll<\/span><\/em><span style=\"font-weight: 400;\"> endpoint (<\/span><a href=\"https:\/\/www.couchbase.com\/blog\/asp-net-crud-nosql-part-2\/\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">see part 2 for more about <\/span><span style=\"font-weight: 400;\">GetAll<\/span><\/a><span style=\"font-weight: 400;\">) to take this into account:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:default decode:true \">SELECT META(w).id, w.*\r\nFROM demo._default.wishlist w\r\nWHERE w.deleted IS MISSING<\/pre>\n<p><span style=\"font-weight: 400;\">I\u2019ve introduced some more SQL++ syntax here: <\/span><em><span style=\"font-weight: 400;\">MISSING<\/span><\/em><span style=\"font-weight: 400;\">. This is a concept that doesn\u2019t exist in relational databases. In relational, any column specified in the query must be defined and must have a value (even if it\u2019s null). With a JSON NoSQL document database, there is no such constraint.<\/span><\/p>\n<h2><b>Improving the index<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">One last point to discuss is indexing. Back in <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/asp-net-crud-nosql-part-2\/\"><span style=\"font-weight: 400;\">part 2<\/span><\/a><span style=\"font-weight: 400;\">, we created a primary index just to get started. However, that index will rarely be the most efficient. <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/learn\/services-and-indexes\/indexes\/global-secondary-indexes.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Creating and tuning indexes<\/span><\/a><span style=\"font-weight: 400;\"> is a deep topic, just as it is in the relational database world.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Fortunately, Couchbase Capella has a built-in <\/span><a href=\"https:\/\/docs.couchbase.com\/cloud\/clusters\/query-service\/query-workbench.html#index-advisor\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\"><strong>Advise<\/strong> tool<\/span><\/a><span style=\"font-weight: 400;\"> that can recommend better indexes. Just click <strong>Advise<\/strong>\u00a0in the Query Workbench (or you can use <\/span><em><span style=\"font-weight: 400;\">ADVISE<\/span><\/em><span style=\"font-weight: 400;\"> syntax).<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13621\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/08\/query_advise_couchbase_sql-asp-net.png\" alt=\"Index adviser recommendations in Couchbase\" width=\"958\" height=\"637\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/query_advise_couchbase_sql-asp-net.png 958w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/query_advise_couchbase_sql-asp-net-300x199.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/query_advise_couchbase_sql-asp-net-768x511.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/query_advise_couchbase_sql-asp-net-400x267.png 400w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/query_advise_couchbase_sql-asp-net-450x300.png 450w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/query_advise_couchbase_sql-asp-net-20x13.png 20w\" sizes=\"auto, (max-width: 958px) 100vw, 958px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">In this case, it gives the following recommendation:<\/span><\/p>\n<pre class=\"decode-attributes:false lang:js decode:true \">\"recommended_indexes\": {\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \"indexes\": [\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 {\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \"index_statement\": \"CREATE INDEX adv_deletedISMISSING ON `default`:`demo`.`_default`.`wishlist`(`deleted` IS MISSING) WHERE `deleted` IS MISSING\",\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \"index_statement_relative\": \"CREATE INDEX adv_deletedISMISSING ON `wishlist`(`deleted` IS MISSING) WHERE `deleted` IS MISSING\",\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \"keyspace_alias\": \"wishlist_w\",\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \"query_context\": \"default:demo._default\",\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \"recommending_rule\": \"Index keys follow order of predicate types: 2. equality\/null\/missing.\"\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }\r\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ]\r\n\u00a0 \u00a0 \u00a0 \u00a0 }<\/pre>\n<p><span style=\"font-weight: 400;\">In the case of our very small amount of wishlist data, this index is probably not worth creating. However, if we were managing the wishlists of an entire eCommerce site (for example), this index would be a good starting point.<\/span><\/p>\n<h2><b>The end of CRUD<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">We\u2019ve reached the end of creating a very simple ASP.NET Core CRUD application with Couchbase. The final API surface looks like:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-13619\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/08\/coucbase-asp-net-full-api-sample.png\" alt=\"Full API example of Couchbase ASP.NET app\" width=\"842\" height=\"603\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/coucbase-asp-net-full-api-sample.png 842w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/coucbase-asp-net-full-api-sample-300x215.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/coucbase-asp-net-full-api-sample-768x550.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/coucbase-asp-net-full-api-sample-20x14.png 20w\" sizes=\"auto, (max-width: 842px) 100vw, 842px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">Here is a breakdown of the concepts in this series, with links to documentation to dive deeper:<\/span><\/p>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><a href=\"https:\/\/docs.couchbase.com\/cloud\/get-started\/get-started.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Setting up Capella<\/span><\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><a href=\"https:\/\/docs.couchbase.com\/dotnet-sdk\/current\/howtos\/managing-connections.html#connection-di\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Setting up .NET dependency injection<\/span><\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><a href=\"https:\/\/docs.couchbase.com\/dotnet-sdk\/current\/howtos\/n1ql-queries-with-sdk.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">SQL++<\/span><\/a><span style=\"font-weight: 400;\"> (sometimes still called &#8220;N1QL&#8221;)<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><a href=\"https:\/\/docs.couchbase.com\/cloud\/clusters\/query-service\/query-workbench.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Query Workbench<\/span><\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><a href=\"https:\/\/docs.couchbase.com\/server\/current\/guides\/select.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">SELECT<\/span><\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><a href=\"https:\/\/docs.couchbase.com\/server\/current\/guides\/insert.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">INSERT<\/span><\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><a href=\"https:\/\/docs.couchbase.com\/server\/current\/guides\/update.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">UPDATE<\/span><\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><a href=\"https:\/\/docs.couchbase.com\/server\/current\/guides\/delete.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">DELETE<\/span><\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><a href=\"https:\/\/docs.couchbase.com\/server\/current\/n1ql\/n1ql-language-reference\/upsert.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">UPSERT<\/span><\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><a href=\"https:\/\/docs.couchbase.com\/server\/current\/guides\/create-index.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">CREATE INDEX<\/span><\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><a href=\"https:\/\/docs.couchbase.com\/cloud\/clusters\/query-service\/query-workbench.html#index-advisor\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Index Advisor<\/span><\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><a href=\"https:\/\/docs.couchbase.com\/dotnet-sdk\/current\/howtos\/kv-operations.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Key-value (.NET SDK)<\/span><\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><a href=\"https:\/\/docs.couchbase.com\/dotnet-sdk\/current\/howtos\/kv-operations.html#crud-operations\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Key-value CRUD operations<\/span><\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><a href=\"https:\/\/docs.couchbase.com\/dotnet-sdk\/current\/howtos\/subdocument-operations.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Sub-document<\/span><\/a><span style=\"font-weight: 400;\"> operations<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><a href=\"https:\/\/docs.couchbase.com\/dotnet-sdk\/current\/howtos\/distributed-acid-transactions-from-the-sdk.html\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">ACID Transactions<\/span><\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/couchbaselabs\/blog-source-code\/tree\/master\/Groves\/135AspNetCoreGettingStartedUpdated2019\/src\/AspNetCoreTutorial\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">The complete source code for this series is available on GitHub<\/span><\/a><span style=\"font-weight: 400;\">.<\/span><\/p>\n<h2><b>What\u2019s next?<\/b><\/h2>\n<p><a href=\"https:\/\/cloud.couchbase.com\/sign-up\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Sign up for a Capella free-trial<\/span><\/a><span style=\"font-weight: 400;\">. The Couchbase Capella DBaaS is the easiest way to get started with Couchbase, and no credit card is required.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Check out the <\/span><a href=\"https:\/\/cloud.couchbase.com\/sign-up\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Couchbase Playground for .NET<\/span><\/a><span style=\"font-weight: 400;\"> examples that you can run right in the browser.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Join the <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/couchbase-on-discord\/\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Couchbase Discord<\/span><\/a><span style=\"font-weight: 400;\"> to ask questions and exchange comments with Couchbase engineers and with other members of the Couchbase community.<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This ASP.NET Core CRUD series is coming to end. We\u2019ve covered setup (part 1), reading with SQL++ (part 2), reading with key-value (part 3), and creating\/updating (part 4). In this last post, we\u2019ll look at the D in CRUD: deleting. [&hellip;]<\/p>\n","protected":false},"author":71,"featured_media":13623,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1811,10126,10127,1816,2201],"tags":[],"ppma_author":[8937],"class_list":["post-13618","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-asp-dotnet","category-c-sharp","category-couchbase-server","category-tools-sdks"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.3 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>ASP.NET Core CRUD with NoSQL: Part 5<\/title>\n<meta name=\"description\" content=\"Learn about deleting with SQL++ or Key-Value, soft-deleting data, improving the index, and more. Sign up for a Capella free-trial and try it for yourself.\" \/>\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.couchbase.com\/blog\/ko\/asp-net-crud-nosql-part-5\/\" \/>\n<meta property=\"og:locale\" content=\"ko_KR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"ASP.NET Core CRUD with NoSQL: Part 5\" \/>\n<meta property=\"og:description\" content=\"Learn about deleting with SQL++ or Key-Value, soft-deleting data, improving the index, and more. Sign up for a Capella free-trial and try it for yourself.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/ko\/asp-net-crud-nosql-part-5\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-08-02T16:46:48+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T03:56:42+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/couchbase-asp-net-crud-app-scaled.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"2560\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Matthew Groves\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@mgroves\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Matthew Groves\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5\ubd84\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/asp-net-crud-nosql-part-5\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/asp-net-crud-nosql-part-5\\\/\"},\"author\":{\"name\":\"Matthew Groves\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/person\\\/3929663e372020321b0152dc4fa65a58\"},\"headline\":\"ASP.NET Core CRUD with NoSQL: Part 5\",\"datePublished\":\"2022-08-02T16:46:48+00:00\",\"dateModified\":\"2025-06-14T03:56:42+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/asp-net-crud-nosql-part-5\\\/\"},\"wordCount\":906,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/asp-net-crud-nosql-part-5\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/08\\\/couchbase-asp-net-crud-app-scaled.jpg\",\"articleSection\":[\".NET\",\"ASP.NET\",\"C#\",\"Couchbase Server\",\"Tools &amp; SDKs\"],\"inLanguage\":\"ko-KR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/asp-net-crud-nosql-part-5\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/asp-net-crud-nosql-part-5\\\/\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/asp-net-crud-nosql-part-5\\\/\",\"name\":\"ASP.NET Core CRUD with NoSQL: Part 5\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/asp-net-crud-nosql-part-5\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/asp-net-crud-nosql-part-5\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/08\\\/couchbase-asp-net-crud-app-scaled.jpg\",\"datePublished\":\"2022-08-02T16:46:48+00:00\",\"dateModified\":\"2025-06-14T03:56:42+00:00\",\"description\":\"Learn about deleting with SQL++ or Key-Value, soft-deleting data, improving the index, and more. Sign up for a Capella free-trial and try it for yourself.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/asp-net-crud-nosql-part-5\\\/#breadcrumb\"},\"inLanguage\":\"ko-KR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/asp-net-crud-nosql-part-5\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/asp-net-crud-nosql-part-5\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/08\\\/couchbase-asp-net-crud-app-scaled.jpg\",\"contentUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/08\\\/couchbase-asp-net-crud-app-scaled.jpg\",\"width\":2560,\"height\":2560,\"caption\":\"Adding DELETE CRUD to ASP.NET Couchbase app\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/asp-net-crud-nosql-part-5\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"ASP.NET Core CRUD with NoSQL: Part 5\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"ko-KR\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/admin-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/person\\\/3929663e372020321b0152dc4fa65a58\",\"name\":\"Matthew Groves\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=gba51e6aacc53995c323a634e4502ef54\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=g\",\"caption\":\"Matthew Groves\"},\"description\":\"Matthew D. Groves is a guy who loves to code. It doesn't matter if it's C#, jQuery, or PHP: he'll submit pull requests for anything. He has been coding professionally ever since he wrote a QuickBASIC point-of-sale app for his parent's pizza shop back in the 90s. He currently works as a Senior Product Marketing Manager for Couchbase. His free time is spent with his family, watching the Reds, and getting involved in the developer community. He is the author of AOP in .NET, Pro Microservices in .NET, a Pluralsight author, and a Microsoft MVP.\",\"sameAs\":[\"https:\\\/\\\/crosscuttingconcerns.com\",\"https:\\\/\\\/x.com\\\/mgroves\"],\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/ko\\\/author\\\/matthew-groves\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"NoSQL\uc744 \uc0ac\uc6a9\ud55c ASP.NET Core CRUD: 5\ubd80","description":"SQL++ \ub610\ub294 \ud0a4-\uac12\uc744 \uc0ac\uc6a9\ud55c \uc0ad\uc81c, \ub370\uc774\ud130 \uc18c\ud504\ud2b8 \uc0ad\uc81c, \uc778\ub371\uc2a4 \uac1c\uc120 \ub4f1\uc5d0 \ub300\ud574 \uc54c\uc544\ubcf4\uc138\uc694. Capella \ubb34\ub8cc \ud3c9\uac00\ud310\uc5d0 \uac00\uc785\ud558\uc5ec \uc9c1\uc811 \uc0ac\uc6a9\ud574 \ubcf4\uc138\uc694.","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.couchbase.com\/blog\/ko\/asp-net-crud-nosql-part-5\/","og_locale":"ko_KR","og_type":"article","og_title":"ASP.NET Core CRUD with NoSQL: Part 5","og_description":"Learn about deleting with SQL++ or Key-Value, soft-deleting data, improving the index, and more. Sign up for a Capella free-trial and try it for yourself.","og_url":"https:\/\/www.couchbase.com\/blog\/ko\/asp-net-crud-nosql-part-5\/","og_site_name":"The Couchbase Blog","article_published_time":"2022-08-02T16:46:48+00:00","article_modified_time":"2025-06-14T03:56:42+00:00","og_image":[{"width":2560,"height":2560,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/couchbase-asp-net-crud-app-scaled.jpg","type":"image\/jpeg"}],"author":"Matthew Groves","twitter_card":"summary_large_image","twitter_creator":"@mgroves","twitter_misc":{"Written by":"Matthew Groves","Est. reading time":"5\ubd84"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/asp-net-crud-nosql-part-5\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/asp-net-crud-nosql-part-5\/"},"author":{"name":"Matthew Groves","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/3929663e372020321b0152dc4fa65a58"},"headline":"ASP.NET Core CRUD with NoSQL: Part 5","datePublished":"2022-08-02T16:46:48+00:00","dateModified":"2025-06-14T03:56:42+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/asp-net-crud-nosql-part-5\/"},"wordCount":906,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/asp-net-crud-nosql-part-5\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/couchbase-asp-net-crud-app-scaled.jpg","articleSection":[".NET","ASP.NET","C#","Couchbase Server","Tools &amp; SDKs"],"inLanguage":"ko-KR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/asp-net-crud-nosql-part-5\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/asp-net-crud-nosql-part-5\/","url":"https:\/\/www.couchbase.com\/blog\/asp-net-crud-nosql-part-5\/","name":"NoSQL\uc744 \uc0ac\uc6a9\ud55c ASP.NET Core CRUD: 5\ubd80","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/asp-net-crud-nosql-part-5\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/asp-net-crud-nosql-part-5\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/couchbase-asp-net-crud-app-scaled.jpg","datePublished":"2022-08-02T16:46:48+00:00","dateModified":"2025-06-14T03:56:42+00:00","description":"SQL++ \ub610\ub294 \ud0a4-\uac12\uc744 \uc0ac\uc6a9\ud55c \uc0ad\uc81c, \ub370\uc774\ud130 \uc18c\ud504\ud2b8 \uc0ad\uc81c, \uc778\ub371\uc2a4 \uac1c\uc120 \ub4f1\uc5d0 \ub300\ud574 \uc54c\uc544\ubcf4\uc138\uc694. Capella \ubb34\ub8cc \ud3c9\uac00\ud310\uc5d0 \uac00\uc785\ud558\uc5ec \uc9c1\uc811 \uc0ac\uc6a9\ud574 \ubcf4\uc138\uc694.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/asp-net-crud-nosql-part-5\/#breadcrumb"},"inLanguage":"ko-KR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/asp-net-crud-nosql-part-5\/"]}]},{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/www.couchbase.com\/blog\/asp-net-crud-nosql-part-5\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/couchbase-asp-net-crud-app-scaled.jpg","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/08\/couchbase-asp-net-crud-app-scaled.jpg","width":2560,"height":2560,"caption":"Adding DELETE CRUD to ASP.NET Couchbase app"},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/asp-net-crud-nosql-part-5\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"ASP.NET Core CRUD with NoSQL: Part 5"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"\uce74\uc6b0\uce58\ubca0\uc774\uc2a4 \ube14\ub85c\uadf8","description":"NoSQL \ub370\uc774\ud130\ubca0\uc774\uc2a4, Couchbase","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"ko-KR"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"\uce74\uc6b0\uce58\ubca0\uc774\uc2a4 \ube14\ub85c\uadf8","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/3929663e372020321b0152dc4fa65a58","name":"\ub9e4\ud29c \uadf8\ub85c\ube0c\uc2a4","image":{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/secure.gravatar.com\/avatar\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=gba51e6aacc53995c323a634e4502ef54","url":"https:\/\/secure.gravatar.com\/avatar\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=g","caption":"Matthew Groves"},"description":"Matthew D. Groves\ub294 \ucf54\ub529\uc744 \uc88b\uc544\ud558\ub294 \uc0ac\ub78c\uc785\ub2c8\ub2e4. C#, jQuery, PHP \ub4f1 \ubb34\uc5c7\uc774\ub4e0 \ud480 \ub9ac\ud018\uc2a4\ud2b8\ub97c \uc81c\ucd9c\ud560 \uc815\ub3c4\ub85c \ucf54\ub529\uc744 \uc88b\uc544\ud569\ub2c8\ub2e4. 90\ub144\ub300\uc5d0 \ubd80\ubaa8\ub2d8\uc758 \ud53c\uc790 \uac00\uac8c\ub97c \uc704\ud574 QuickBASIC POS \uc571\uc744 \ub9cc\ub4e0 \uc774\ud6c4\ub85c \uc804\ubb38\uc801\uc73c\ub85c \ucf54\ub529\uc744 \ud574\uc654\uc2b5\ub2c8\ub2e4. \ud604\uc7ac Couchbase\uc758 \uc120\uc784 \uc81c\ud488 \ub9c8\ucf00\ud305 \uad00\ub9ac\uc790\ub85c \uc77c\ud558\uace0 \uc788\uc2b5\ub2c8\ub2e4. \uc5ec\uac00 \uc2dc\uac04\uc5d0\ub294 \uac00\uc871\uacfc \ud568\uaed8 \ucd95\uad6c \uacbd\uae30\ub97c \uad00\ub78c\ud558\uace0 \uac1c\ubc1c\uc790 \ucee4\ubba4\ub2c8\ud2f0\uc5d0 \ucc38\uc5ec\ud558\uba70 \uc2dc\uac04\uc744 \ubcf4\ub0c5\ub2c8\ub2e4. \uadf8\ub294 .NET\uc758 AOP, .NET\uc758 \ud504\ub85c \ub9c8\uc774\ud06c\ub85c\uc11c\ube44\uc2a4, Pluralsight \uc800\uc790, Microsoft MVP\uc758 \uc800\uc790\uc774\uae30\ub3c4 \ud569\ub2c8\ub2e4.","sameAs":["https:\/\/crosscuttingconcerns.com","https:\/\/x.com\/mgroves"],"url":"https:\/\/www.couchbase.com\/blog\/ko\/author\/matthew-groves\/"}]}},"acf":[],"authors":[{"term_id":8937,"user_id":71,"is_guest":0,"slug":"matthew-groves","display_name":"Matthew Groves","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/posts\/13618","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/users\/71"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/comments?post=13618"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/posts\/13618\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/media\/13623"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/media?parent=13618"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/categories?post=13618"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/tags?post=13618"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/ppma_author?post=13618"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}