mirror of
https://github.com/dotnetcore/FreeSql.git
synced 2026-02-11 02:40:55 +08:00
update
@@ -1,128 +1,147 @@
|
||||
[中文](%e8%81%94%e7%ba%a7%e4%bf%9d%e5%ad%98) | **English**
|
||||
|
||||
The cascade save function can save the one-to-many or many-to-many navigation properties when saving the object. This document introduces cascading saving to avoid misuse by developers.
|
||||
## SaveMany Savemany save manually
|
||||
|
||||
## One-to-Many Cascade Saving
|
||||
|
||||
Method 1: Save intact, compare the existing data in the table, and calculate the added, modified, and deleted data
|
||||
Save completely, compare the existing data in the table, and calculate the execution of addition, modification and deletion.
|
||||
|
||||
```csharp
|
||||
var repo = fsql.GetRepository<T>();
|
||||
repo.Insert(item);
|
||||
repo.SaveMany(item, "Childs");
|
||||
```
|
||||
|
||||
- It is possible to delete the existing data in the table, confirm?
|
||||
- When the Childs property is Empty, delete all the table data of Childs in the item, confirm?
|
||||
- When saving Topics, the subordinate collection properties of Childs\[0-..\] are not saved, only the current level of Topics. Confirm?
|
||||
|
||||
Method 2: Additional save, do not delete the existing data in the table
|
||||
|
||||
```csharp
|
||||
var repo = fsql.GetRepository<T>();
|
||||
repo.DbContextOptions.EnableCascadeSave = true; //Need to be opened manually
|
||||
repo.Insert(item);
|
||||
```
|
||||
- Do not delete the existing data in the table, confirm?
|
||||
- When the Childs property is Empty, do nothing, confirm?
|
||||
- When saving Childs, the subordinate collection properties of Childs\[0-..\] will also be saved, _down 18 levels_, confirm?
|
||||
|
||||
> _Down 18 levels_ is, the navigation properties that exist in the navigation properties, in which there are navigation properties.
|
||||
|
||||
> The navigation properties of the navigation properties are retrieved layer by layer, and the InsertOrUpdate operation is performed together.
|
||||
|
||||
## Many-to-Many Cascade Saving
|
||||
|
||||
There is only one mechanism: complete preservation.
|
||||
|
||||
> Enabling the `EnableCascadeSave` option or `SaveMany` is a complete save.
|
||||
|
||||
---
|
||||
|
||||
Test 1: Additional Save OneToMany
|
||||
|
||||
```csharp
|
||||
[Table(Name = "EAUNL_OTMP_CT")]
|
||||
class CagetoryParent {
|
||||
class Cagetory
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
|
||||
public Guid ParentId { get; set; }
|
||||
[Navigate(nameof(ParentId))]
|
||||
public List<CagetoryParent> Childs { get; set; }
|
||||
public List<Cagetory> Childs { get; set; }
|
||||
}
|
||||
|
||||
//item = ...;
|
||||
var repo = fsql.GetRepository<Cagetory>();
|
||||
repo.Insert(item);
|
||||
repo.SaveMany(item, "Childs");
|
||||
```
|
||||
|
||||
-[OneToMany] and [ManyToMany] navigation attributes are supported
|
||||
-Save only children, not recursive tracing down
|
||||
-When children is empty, delete all children table data existing in item, and confirm?
|
||||
-Advantages: simple mechanism, good control and safety
|
||||
-Disadvantages: not intelligent
|
||||
|
||||
## EnableCascadeSave DbContext/Repository
|
||||
|
||||
DbContext/Repository EnableCascadeSave enables recursive tracing of the OneToOne, OneToMany, and ManyToMany navigation properties of objects when they are saved. This document describes the mechanism to prevent misuse.
|
||||
|
||||
1. OneToOne cascade save
|
||||
|
||||
> v3.2.606 + support, and support [cascade deletion function](https://github.com/dotnetcore/FreeSql/wiki/%e5%88%a0%e9%99%a4#ibaserepository-%E7%BA%A7%E8%81%94%E5%88%A0%E9%99%A4)
|
||||
|
||||
2. OneToMany appends or updates the sub table without deleting the existing data of the sub table
|
||||
|
||||
```c#
|
||||
var repo = fsql. GetRepository<Cagetory>();
|
||||
repo. DbContextOptions. EnableCascadeSave = true; // Manual opening required
|
||||
repo. Insert(item);
|
||||
```
|
||||
|
||||
-Do not delete the existing data of children sub table. Are you sure?
|
||||
-When the children attribute is empty, do not do anything. Confirm?
|
||||
-When you save children, you will also save the child set attributes of children \ [0 -.. \]. Go down to 18 layers and confirm?
|
||||
|
||||
>For example, in the [type] table, there is set attribute [article] below and set attribute [comment] below [article].
|
||||
|
||||
>When saving the [type] table object, it will retrieve the set attribute [article], and then if the [article] is saved, it will continue to retrieve the set attribute [comment]. Do insertorupdate operation together.
|
||||
|
||||
3. ManyToMany completely compares and saves the intermediate table and appends the external table
|
||||
|
||||
Compare and save the intermediate table completely, compare the existing data of the [many to many] intermediate table, and calculate the execution of addition, modification and deletion.
|
||||
|
||||
Append external tables, only append without updating.
|
||||
|
||||
-This table song
|
||||
-External table tag
|
||||
-Intermediate table Songtag
|
||||
|
||||
---
|
||||
|
||||
Test 1: append and save OneToMany
|
||||
|
||||
```csharp
|
||||
|
||||
[Fact]
|
||||
public void TestOneToManyParent() {
|
||||
var repo = fsql.GetRepository<CagetoryParent>();
|
||||
public void TestOneToManyParent()
|
||||
{
|
||||
var repo = fsql.GetRepository<Cagetory>();
|
||||
repo.DbContextOptions.EnableCascadeSave = true;
|
||||
var cts = new[] {
|
||||
new CagetoryParent
|
||||
var cts = new[]
|
||||
{
|
||||
new Cagetory
|
||||
{
|
||||
Name = "Category1",
|
||||
Childs = new List<CagetoryParent>(new[]
|
||||
Name = "class1",
|
||||
Childs = new List<Cagetory>(new[]
|
||||
{
|
||||
new CagetoryParent { Name = "Category1_1" },
|
||||
new CagetoryParent { Name = "Category1_2" },
|
||||
new CagetoryParent { Name = "Category1_3" }
|
||||
new Cagetory { Name = "class1_1" },
|
||||
new Cagetory { Name = "class1_2" },
|
||||
new Cagetory { Name = "class1_3" }
|
||||
})
|
||||
},
|
||||
new CagetoryParent
|
||||
new Cagetory
|
||||
{
|
||||
Name = "Category2",
|
||||
Childs = new List<CagetoryParent>(new[]
|
||||
Name = "class2",
|
||||
Childs = new List<Cagetory>(new[]
|
||||
{
|
||||
new CagetoryParent { Name = "Category2_1" },
|
||||
new CagetoryParent { Name = "Category2_2" }
|
||||
new Cagetory { Name = "class2_1" },
|
||||
new Cagetory { Name = "class2_2" }
|
||||
})
|
||||
}
|
||||
};
|
||||
repo.Insert(cts);
|
||||
//Perform table creation and insert data:
|
||||
//INSERT INTO "EAUNL_OTMP_CT"("Id", "Name", "ParentId") VALUES('5d90afcb-ed57-f6f4-0082-cb6b78eaaf9f', 'Category1', '00000000-0000-0000-0000-000000000000'), ('5d90afcb-ed57-f6f4-0082-cb6c5b531b3e', 'Category2', '00000000-0000-0000-0000-000000000000')
|
||||
//INSERT INTO "EAUNL_OTMP_CT"("Id", "Name", "ParentId") VALUES('5d90afcb-ed57-f6f4-0082-cb6d0c1c5f1a', 'Category1_1', '5d90afcb-ed57-f6f4-0082-cb6b78eaaf9f'), ('5d90afcb-ed57-f6f4-0082-cb6e74bd8eef', 'Category1_2', '5d90afcb-ed57-f6f4-0082-cb6b78eaaf9f'), ('5d90afcb-ed57-f6f4-0082-cb6f6267cc5f', 'Category1_3', '5d90afcb-ed57-f6f4-0082-cb6b78eaaf9f'), ('5d90afcb-ed57-f6f4-0082-cb7057c41d46', 'Category2_1', '5d90afcb-ed57-f6f4-0082-cb6c5b531b3e'), ('5d90afcb-ed57-f6f4-0082-cb7156e0375e', 'Category2_2', '5d90afcb-ed57-f6f4-0082-cb6c5b531b3e')
|
||||
cts[0].Name = "Category11";
|
||||
//To create a table and insert data:
|
||||
//INSERT INTO "Cagetory"("Id", "Name", "ParentId") VALUES('5d90afcb-ed57-f6f4-0082-cb6b78eaaf9f', 'class1', '00000000-0000-0000-0000-000000000000'), ('5d90afcb-ed57-f6f4-0082-cb6c5b531b3e', 'class2', '00000000-0000-0000-0000-000000000000')
|
||||
//INSERT INTO "Cagetory"("Id", "Name", "ParentId") VALUES('5d90afcb-ed57-f6f4-0082-cb6d0c1c5f1a', 'class1_1', '5d90afcb-ed57-f6f4-0082-cb6b78eaaf9f'), ('5d90afcb-ed57-f6f4-0082-cb6e74bd8eef', 'class1_2', '5d90afcb-ed57-f6f4-0082-cb6b78eaaf9f'), ('5d90afcb-ed57-f6f4-0082-cb6f6267cc5f', 'class1_3', '5d90afcb-ed57-f6f4-0082-cb6b78eaaf9f'), ('5d90afcb-ed57-f6f4-0082-cb7057c41d46', 'class2_1', '5d90afcb-ed57-f6f4-0082-cb6c5b531b3e'), ('5d90afcb-ed57-f6f4-0082-cb7156e0375e', 'class2_2', '5d90afcb-ed57-f6f4-0082-cb6c5b531b3e')
|
||||
cts[0].Name = "class11";
|
||||
cts[0].Childs.Clear();
|
||||
cts[1].Name = "Category22";
|
||||
cts[1].Name = "class22";
|
||||
cts[1].Childs.Clear();
|
||||
repo.Update(cts);
|
||||
//UPDATE "EAUNL_OTMP_CT" SET "Name" = CASE "Id"
|
||||
//WHEN '5d90afcb-ed57-f6f4-0082-cb6b78eaaf9f' THEN 'Category11'
|
||||
//WHEN '5d90afcb-ed57-f6f4-0082-cb6c5b531b3e' THEN 'Category22' END
|
||||
//UPDATE "Cagetory" SET "Name" = CASE "Id"
|
||||
//WHEN '5d90afcb-ed57-f6f4-0082-cb6b78eaaf9f' THEN 'class11'
|
||||
//WHEN '5d90afcb-ed57-f6f4-0082-cb6c5b531b3e' THEN 'class22' END
|
||||
//WHERE ("Id" IN ('5d90afcb-ed57-f6f4-0082-cb6b78eaaf9f','5d90afcb-ed57-f6f4-0082-cb6c5b531b3e'))
|
||||
//After Childs.Clear, the delete sub-collection operation is not executed, indicating that a complete comparison has not been made
|
||||
cts[0].Name = "Category111";
|
||||
//Childs.Clear After that, the operation of deleting subsets was not performed, indicating that no complete comparison was made
|
||||
cts[0].Name = "class111";
|
||||
cts[0].Childs.Clear();
|
||||
cts[0].Childs.Add(new CagetoryParent { Name = "Category1_33" });
|
||||
cts[1].Name = "Category222";
|
||||
cts[0].Childs.Add(new Cagetory { Name = "class1_33" });
|
||||
cts[1].Name = "class222";
|
||||
cts[1].Childs.Clear();
|
||||
cts[1].Childs.Add(new CagetoryParent { Name = "Category2_22" });
|
||||
cts[1].Childs.Add(new Cagetory { Name = "class2_22" });
|
||||
repo.Update(cts);
|
||||
//UPDATE "EAUNL_OTMP_CT" SET "Name" = CASE "Id"
|
||||
//WHEN '5d90afcb-ed57-f6f4-0082-cb6b78eaaf9f' THEN 'Category111'
|
||||
//WHEN '5d90afcb-ed57-f6f4-0082-cb6c5b531b3e' THEN 'Category222' END
|
||||
//UPDATE "Cagetory" SET "Name" = CASE "Id"
|
||||
//WHEN '5d90afcb-ed57-f6f4-0082-cb6b78eaaf9f' THEN 'class111'
|
||||
//WHEN '5d90afcb-ed57-f6f4-0082-cb6c5b531b3e' THEN 'class222' END
|
||||
//WHERE ("Id" IN ('5d90afcb-ed57-f6f4-0082-cb6b78eaaf9f','5d90afcb-ed57-f6f4-0082-cb6c5b531b3e'))
|
||||
//INSERT INTO "EAUNL_OTMP_CT"("Id", "Name", "ParentId") VALUES('5d90afe8-ed57-f6f4-0082-cb725df546ea', 'Category1_33', '5d90afcb-ed57-f6f4-0082-cb6b78eaaf9f'), ('5d90afe8-ed57-f6f4-0082-cb7338a6214c', 'Category2_22', '5d90afcb-ed57-f6f4-0082-cb6c5b531b3e')
|
||||
//INSERT INTO "Cagetory"("Id", "Name", "ParentId") VALUES('5d90afe8-ed57-f6f4-0082-cb725df546ea', 'class1_33', '5d90afcb-ed57-f6f4-0082-cb6b78eaaf9f'), ('5d90afe8-ed57-f6f4-0082-cb7338a6214c', 'class2_22', '5d90afcb-ed57-f6f4-0082-cb6c5b531b3e')
|
||||
}
|
||||
```
|
||||
|
||||
Test 2: Additional Save ManyToMany
|
||||
---
|
||||
|
||||
Test 2: Full save ManyToMany
|
||||
|
||||
```csharp
|
||||
[Table(Name = "EAUNL_MTM_SONG")]
|
||||
class Song {
|
||||
class Song
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public List<Tag> Tags { get; set; }
|
||||
}
|
||||
[Table(Name = "EAUNL_MTM_TAG")]
|
||||
class Tag {
|
||||
class Tag
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string TagName { get; set; }
|
||||
public List<Song> Songs { get; set; }
|
||||
}
|
||||
[Table(Name = "EAUNL_MTM_SONGTAG")]
|
||||
class SongTag {
|
||||
class SongTag
|
||||
{
|
||||
public Guid SongId { get; set; }
|
||||
public Song Song { get; set; }
|
||||
public Guid TagId { get; set; }
|
||||
@@ -130,18 +149,20 @@ class SongTag {
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestManyToMany() {
|
||||
var tags = new[] {
|
||||
new Tag { TagName = "Pop" },
|
||||
new Tag { TagName = "Modern music" },
|
||||
new Tag { TagName = "Next-generation music" },
|
||||
new Tag { TagName = "Rock" }
|
||||
public void TestManyToMany()
|
||||
{
|
||||
var tags = new[]
|
||||
{
|
||||
new Tag { TagName = "pop music" },
|
||||
new Tag { TagName = "the post-80s generation" },
|
||||
new Tag { TagName = "the post-00s generation" },
|
||||
new Tag { TagName = "Rock music" }
|
||||
};
|
||||
var ss = new[]
|
||||
{
|
||||
new Song
|
||||
{
|
||||
Name = "Take Me To Your Heart.mp3",
|
||||
Name = "love you forever.mp3",
|
||||
Tags = new List<Tag>(new[]
|
||||
{
|
||||
tags[0], tags[1]
|
||||
@@ -149,7 +170,7 @@ public void TestManyToMany() {
|
||||
},
|
||||
new Song
|
||||
{
|
||||
Name = "Kiss Me More.mp3",
|
||||
Name = "Li Bai.mp3",
|
||||
Tags = new List<Tag>(new[]
|
||||
{
|
||||
tags[0], tags[2]
|
||||
@@ -159,49 +180,49 @@ public void TestManyToMany() {
|
||||
var repo = fsql.GetRepository<Song>();
|
||||
repo.DbContextOptions.EnableCascadeSave = true;
|
||||
repo.Insert(ss);
|
||||
//INSERT INTO "EAUNL_MTM_SONG"("Id", "Name") VALUES('5d90fdb3-6a6b-2c58-00c8-37974177440d', 'Take Me To Your Heart.mp3'), ('5d90fdb3-6a6b-2c58-00c8-37987f29b197', 'Kiss Me More.mp3')
|
||||
//INSERT INTO "EAUNL_MTM_TAG"("Id", "TagName") VALUES('5d90fdb7-6a6b-2c58-00c8-37991ead4f05', 'Pop'), ('5d90fdbd-6a6b-2c58-00c8-379a0432a09c', 'Modern music')
|
||||
//INSERT INTO "EAUNL_MTM_SONGTAG"("SongId", "TagId") VALUES('5d90fdb3-6a6b-2c58-00c8-37974177440d', '5d90fdb7-6a6b-2c58-00c8-37991ead4f05'), ('5d90fdb3-6a6b-2c58-00c8-37974177440d', '5d90fdbd-6a6b-2c58-00c8-379a0432a09c')
|
||||
//INSERT INTO "EAUNL_MTM_TAG"("Id", "TagName") VALUES('5d90fdcc-6a6b-2c58-00c8-379b5af59d25', 'Next-generation music')
|
||||
//INSERT INTO "EAUNL_MTM_SONGTAG"("SongId", "TagId") VALUES('5d90fdb3-6a6b-2c58-00c8-37987f29b197', '5d90fdb7-6a6b-2c58-00c8-37991ead4f05'), ('5d90fdb3-6a6b-2c58-00c8-37987f29b197', '5d90fdcc-6a6b-2c58-00c8-379b5af59d25')
|
||||
//INSERT INTO "Song"("Id", "Name") VALUES('5d90fdb3-6a6b-2c58-00c8-37974177440d', 'love you forever.mp3'), ('5d90fdb3-6a6b-2c58-00c8-37987f29b197', 'Li Bai.mp3')
|
||||
//INSERT INTO "Tag"("Id", "TagName") VALUES('5d90fdb7-6a6b-2c58-00c8-37991ead4f05', 'pop music'), ('5d90fdbd-6a6b-2c58-00c8-379a0432a09c', 'the post-80s generation')
|
||||
//INSERT INTO "SongTag"("SongId", "TagId") VALUES('5d90fdb3-6a6b-2c58-00c8-37974177440d', '5d90fdb7-6a6b-2c58-00c8-37991ead4f05'), ('5d90fdb3-6a6b-2c58-00c8-37974177440d', '5d90fdbd-6a6b-2c58-00c8-379a0432a09c')
|
||||
//INSERT INTO "Tag"("Id", "TagName") VALUES('5d90fdcc-6a6b-2c58-00c8-379b5af59d25', 'the post-00s generation')
|
||||
//INSERT INTO "SongTag"("SongId", "TagId") VALUES('5d90fdb3-6a6b-2c58-00c8-37987f29b197', '5d90fdb7-6a6b-2c58-00c8-37991ead4f05'), ('5d90fdb3-6a6b-2c58-00c8-37987f29b197', '5d90fdcc-6a6b-2c58-00c8-379b5af59d25')
|
||||
|
||||
ss[0].Name = "Take Me To Your Heart.mp5";
|
||||
ss[0].Name = "love you forever.mp5";
|
||||
ss[0].Tags.Clear();
|
||||
ss[0].Tags.Add(tags[0]);
|
||||
ss[1].Name = "Kiss Me More.mp5";
|
||||
ss[1].Name = "Li Bai.mp5";
|
||||
ss[1].Tags.Clear();
|
||||
ss[1].Tags.Add(tags[3]);
|
||||
repo.Update(ss);
|
||||
//UPDATE "EAUNL_MTM_SONG" SET "Name" = CASE "Id"
|
||||
//WHEN '5d90fdb3-6a6b-2c58-00c8-37974177440d' THEN 'Take Me To Your Heart.mp5'
|
||||
//WHEN '5d90fdb3-6a6b-2c58-00c8-37987f29b197' THEN 'Kiss Me More.mp5' END
|
||||
//UPDATE "Song" SET "Name" = CASE "Id"
|
||||
//WHEN '5d90fdb3-6a6b-2c58-00c8-37974177440d' THEN 'love you forever.mp5'
|
||||
//WHEN '5d90fdb3-6a6b-2c58-00c8-37987f29b197' THEN 'Li Bai.mp5' END
|
||||
//WHERE ("Id" IN ('5d90fdb3-6a6b-2c58-00c8-37974177440d','5d90fdb3-6a6b-2c58-00c8-37987f29b197'))
|
||||
|
||||
//SELECT a."SongId", a."TagId"
|
||||
//FROM "EAUNL_MTM_SONGTAG" a
|
||||
//FROM "SongTag" a
|
||||
//WHERE (a."SongId" = '5d90fdb3-6a6b-2c58-00c8-37974177440d')
|
||||
|
||||
//DELETE FROM "EAUNL_MTM_SONGTAG" WHERE ("SongId" = '5d90fdb3-6a6b-2c58-00c8-37974177440d' AND "TagId" = '5d90fdbd-6a6b-2c58-00c8-379a0432a09c')
|
||||
//INSERT INTO "EAUNL_MTM_TAG"("Id", "TagName") VALUES('5d90febd-6a6b-2c58-00c8-379c21acfc72', 'Rock')
|
||||
//DELETE FROM "SongTag" WHERE ("SongId" = '5d90fdb3-6a6b-2c58-00c8-37974177440d' AND "TagId" = '5d90fdbd-6a6b-2c58-00c8-379a0432a09c')
|
||||
//INSERT INTO "Tag"("Id", "TagName") VALUES('5d90febd-6a6b-2c58-00c8-379c21acfc72', 'Rock music')
|
||||
|
||||
//SELECT a."SongId", a."TagId"
|
||||
//FROM "EAUNL_MTM_SONGTAG" a
|
||||
//FROM "SongTag" a
|
||||
//WHERE (a."SongId" = '5d90fdb3-6a6b-2c58-00c8-37987f29b197')
|
||||
|
||||
//DELETE FROM "EAUNL_MTM_SONGTAG" WHERE ("SongId" = '5d90fdb3-6a6b-2c58-00c8-37987f29b197' AND "TagId" = '5d90fdb7-6a6b-2c58-00c8-37991ead4f05' OR "SongId" = '5d90fdb3-6a6b-2c58-00c8-37987f29b197' AND "TagId" = '5d90fdcc-6a6b-2c58-00c8-379b5af59d25')
|
||||
//INSERT INTO "EAUNL_MTM_SONGTAG"("SongId", "TagId") VALUES('5d90fdb3-6a6b-2c58-00c8-37987f29b197', '5d90febd-6a6b-2c58-00c8-379c21acfc72')
|
||||
//DELETE FROM "SongTag" WHERE ("SongId" = '5d90fdb3-6a6b-2c58-00c8-37987f29b197' AND "TagId" = '5d90fdb7-6a6b-2c58-00c8-37991ead4f05' OR "SongId" = '5d90fdb3-6a6b-2c58-00c8-37987f29b197' AND "TagId" = '5d90fdcc-6a6b-2c58-00c8-379b5af59d25')
|
||||
//INSERT INTO "SongTag"("SongId", "TagId") VALUES('5d90fdb3-6a6b-2c58-00c8-37987f29b197', '5d90febd-6a6b-2c58-00c8-379c21acfc72')
|
||||
|
||||
ss[0].Name = "Take Me To Your Heart.mp4";
|
||||
ss[0].Name = "love you forever.mp4";
|
||||
ss[0].Tags.Clear();
|
||||
ss[1].Name = "Kiss Me More.mp4";
|
||||
ss[1].Name = "Li Bai.mp4";
|
||||
ss[1].Tags.Clear();
|
||||
repo.Update(ss);
|
||||
//DELETE FROM "EAUNL_MTM_SONGTAG" WHERE ("SongId" = '5d90fdb3-6a6b-2c58-00c8-37974177440d')
|
||||
//DELETE FROM "EAUNL_MTM_SONGTAG" WHERE ("SongId" = '5d90fdb3-6a6b-2c58-00c8-37987f29b197')
|
||||
//DELETE FROM "SongTag" WHERE ("SongId" = '5d90fdb3-6a6b-2c58-00c8-37974177440d')
|
||||
//DELETE FROM "SongTag" WHERE ("SongId" = '5d90fdb3-6a6b-2c58-00c8-37987f29b197')
|
||||
|
||||
//UPDATE "EAUNL_MTM_SONG" SET "Name" = CASE "Id"
|
||||
//WHEN '5d90fdb3-6a6b-2c58-00c8-37974177440d' THEN 'Take Me To Your Heart.mp4'
|
||||
//WHEN '5d90fdb3-6a6b-2c58-00c8-37987f29b197' THEN 'Kiss Me More.mp4' END
|
||||
//UPDATE "Song" SET "Name" = CASE "Id"
|
||||
//WHEN '5d90fdb3-6a6b-2c58-00c8-37974177440d' THEN 'love you forever.mp4'
|
||||
//WHEN '5d90fdb3-6a6b-2c58-00c8-37987f29b197' THEN 'Li Bai.mp4' END
|
||||
//WHERE ("Id" IN ('5d90fdb3-6a6b-2c58-00c8-37974177440d','5d90fdb3-6a6b-2c58-00c8-37987f29b197'))
|
||||
}
|
||||
```
|
||||
```
|
||||
1
删除.md
1
删除.md
@@ -118,7 +118,6 @@ repo.Insert(new UserGroup
|
||||
//INSERT INTO "user"("username", "password", "groupid") VALUES('admin01', 'pwd01', 1), ('admin02', 'pwd02', 1), ('admin03', 'pwd03', 1) RETURNING "id" as "Id", "username" as "Username", "password" as "Password", "groupid" as "GroupId"
|
||||
//INSERT INTO "userext"("userid", "remark") VALUES(3, '用户备注01'), (4, '用户备注02'), (5, '用户备注03')
|
||||
|
||||
|
||||
var groups = repo.Select
|
||||
.IncludeMany(a => a.Users,
|
||||
then => then.Include(b => b.UserExt))
|
||||
|
||||
20
联级保存.md
20
联级保存.md
@@ -21,7 +21,7 @@ repo.Insert(item);
|
||||
repo.SaveMany(item, "Childs");
|
||||
```
|
||||
|
||||
- 支持【OneToMany】、【ManyToMany】导航属性
|
||||
- 支持 OneToMany、ManyToMany 导航属性
|
||||
- 只保存 Childs,不向下递归追朔
|
||||
- 当 Childs 为 Empty 时,删除 item 存在的 Childs 所有表数据,确认?
|
||||
- 优点:机制简单,好把控,安全
|
||||
@@ -29,13 +29,13 @@ repo.SaveMany(item, "Childs");
|
||||
|
||||
## EnableCascadeSave 仓储级联保存
|
||||
|
||||
DbContext/Repository EnableCascadeSave 可实现保存对象的时候,追朔其【OneToOne】、【OneToMany】、【ManyToMany】导航属性也一并保存,本文档说明实现的机制防止误用。
|
||||
DbContext/Repository EnableCascadeSave 可实现保存对象的时候,递归追朔其 OneToOne、OneToMany、ManyToMany 导航属性也一并保存,本文档说明实现的机制防止误用。
|
||||
|
||||
1、OneToOne 级联保存
|
||||
|
||||
> v3.2.606+ 支持,并且支持级联删除功能,
|
||||
> v3.2.606+ 支持,并且支持[级联删除功能](https://github.com/dotnetcore/FreeSql/wiki/%e5%88%a0%e9%99%a4#ibaserepository-%E7%BA%A7%E8%81%94%E5%88%A0%E9%99%A4)
|
||||
|
||||
2、OneToMany 追加保存,不删除表已存在的数据
|
||||
2、OneToMany 追加或更新子表,不删除子表已存在的数据
|
||||
|
||||
```csharp
|
||||
var repo = fsql.GetRepository<Cagetory>();
|
||||
@@ -43,7 +43,7 @@ repo.DbContextOptions.EnableCascadeSave = true; //需要手工开启
|
||||
repo.Insert(item);
|
||||
```
|
||||
|
||||
- 不删除表已存在的数据,确认?
|
||||
- 不删除 Childs 子表已存在的数据,确认?
|
||||
- 当 Childs 属性为 Empty 时,不做任何操作,确认?
|
||||
- 保存 Childs 的时候,还会保存 Childs\[0-..\] 的下级集合属性,向下18层,确认?
|
||||
|
||||
@@ -51,11 +51,15 @@ repo.Insert(item);
|
||||
|
||||
> 保存【类型】表对象的时候,他会向下检索出集合属性【文章】,然后如果【文章】被保存的时候,再继续向下检索出集合属性【评论】。一起做 InsertOrUpdate 操作。
|
||||
|
||||
3、ManyToMany 完整保存
|
||||
3、ManyToMany 完整对比保存中间表,追加外部表
|
||||
|
||||
完整保存,对比【多对多】中间表已存在的数据,计算出添加、修改、删除执行。
|
||||
完整对比保存中间表,对比【多对多】中间表已存在的数据,计算出添加、修改、删除执行。
|
||||
|
||||
> ManyToMany 模型下,开启 EnableCascadeSave 或者 SaveMany 都是完整保存。
|
||||
追加外部表,只追加不更新。
|
||||
|
||||
- 本表 Song
|
||||
- 外部表 Tag
|
||||
- 中间表 SongTag
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user