Skip to content

Commit f245981

Browse files
authored
Merge pull request #1975 from ly303550688/master
增加sqlite批量插入方式
2 parents 37d8035 + de9d7d3 commit f245981

File tree

2 files changed

+135
-2
lines changed

2 files changed

+135
-2
lines changed

FreeSql.Tests/FreeSql.Tests.Provider.Sqlite.Data/Sqlite/Curd/SqliteInsertTest.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using FreeSql.DataAnnotations;
1+
using FreeSql.DataAnnotations;
22
using System;
33
using System.Collections.Generic;
44
using System.Linq;
@@ -138,5 +138,27 @@ public void AsTable()
138138
sql = insert.AppendData(items).IgnoreColumns(a => new { a.Title, a.CreateTime }).AsTable(a => "Topic_InsertAsTable").ToSql();
139139
Assert.Equal("INSERT INTO \"Topic_InsertAsTable\"(\"Clicks\") VALUES(@Clicks_0), (@Clicks_1), (@Clicks_2), (@Clicks_3), (@Clicks_4), (@Clicks_5), (@Clicks_6), (@Clicks_7), (@Clicks_8), (@Clicks_9)", sql);
140140
}
141+
142+
[Fact]
143+
public void BulkInsert()
144+
{
145+
g.sqlite.Delete<Topic>().Where(m => true).ExecuteAffrows();
146+
var list = new List<Topic>();
147+
for (int i = 0; i < 10; i++)
148+
{
149+
list.Add(new Topic { Id = i, Clicks = i * 2, Title = "BULK" + i.ToString(), CreateTime = DateTime.Now });
150+
}
151+
insert.AppendData(list).BulkInsert();
152+
Assert.Equal(10, g.sqlite.Select<Topic>().Where(m => m.Title.StartsWith("BULK")).Count());
153+
154+
g.sqlite.Delete<Topic>().Where(m => true).ExecuteAffrows();
155+
g.sqlite.Transaction(() =>
156+
{
157+
g.sqlite.Insert(list).BulkInsert();
158+
Assert.Equal(10, g.sqlite.Select<Topic>().Where(m => m.Title.StartsWith("BULK")).Count());
159+
});
160+
}
161+
162+
141163
}
142164
}

Providers/FreeSql.Provider.Sqlite/SqliteExtensions.cs

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
public static partial class FreeSqlSqliteGlobalExtensions
1+
using FreeSql;
2+
using System;
3+
using System.Data;
4+
using System.Data.Common;
5+
using System.Text;
6+
using static System.Runtime.CompilerServices.RuntimeHelpers;
7+
8+
public static partial class FreeSqlSqliteGlobalExtensions
29
{
310

411
/// <summary>
@@ -9,4 +16,108 @@
916
/// <returns></returns>
1017
public static string FormatSqlite(this string that, params object[] args) => _sqliteAdo.Addslashes(that, args);
1118
static FreeSql.Sqlite.SqliteAdo _sqliteAdo = new FreeSql.Sqlite.SqliteAdo();
19+
public static void BulkInsert<T>(this IInsert<T> that) where T : class
20+
{
21+
var insert = that as FreeSql.Sqlite.Curd.SqliteInsert<T>;
22+
if (insert == null) throw new Exception(CoreErrorStrings.S_Features_Unique("BulkInsert", "Sqlite"));
23+
24+
var dt = that.ToDataTable();
25+
if (dt.Rows.Count == 0) return;
26+
27+
Action<DbTransaction> writeToServer = (tran) =>
28+
{
29+
var insertCmd = tran.Connection.CreateCommand();
30+
var copyFromCommand = new StringBuilder().Append("INSERT INTO ").Append(insert._commonUtils.QuoteSqlName(dt.TableName)).Append("(");
31+
var colIndex = 0;
32+
foreach (DataColumn col in dt.Columns)
33+
{
34+
if (colIndex++ > 0) copyFromCommand.Append(", ");
35+
copyFromCommand.Append(insert._commonUtils.QuoteSqlName(col.ColumnName));
36+
}
37+
copyFromCommand.Append(") VALUES ( ");
38+
colIndex = 0;
39+
foreach (DataColumn col in dt.Columns)
40+
{
41+
if (colIndex++ > 0) copyFromCommand.Append(", ");
42+
copyFromCommand.Append("@").Append(col.ColumnName);
43+
44+
var p = insertCmd.CreateParameter();
45+
p.ParameterName = col.ColumnName;
46+
var trycol = insert._table.Columns[col.ColumnName];
47+
var tp = insert._orm.CodeFirst.GetDbInfo(trycol.Attribute.MapType)?.type;
48+
49+
insertCmd.Parameters.Add(p);
50+
}
51+
copyFromCommand.Append(")");
52+
insertCmd.CommandText = copyFromCommand.ToString();
53+
54+
foreach (DataRow r in dt.Rows)
55+
{
56+
foreach (DataColumn c in dt.Columns)
57+
{
58+
var p = insertCmd.Parameters[c.ColumnName];
59+
p.Value = r[c.ColumnName];
60+
}
61+
insertCmd.ExecuteNonQuery();
62+
}
63+
};
64+
65+
try
66+
{
67+
if (insert._connection == null && insert._transaction == null)
68+
{
69+
if (insert._orm.Ado?.TransactionCurrentThread != null)
70+
{
71+
writeToServer(insert._orm.Ado.TransactionCurrentThread);
72+
}
73+
else
74+
{
75+
using (var conn = insert._orm.Ado.MasterPool.Get())
76+
{
77+
using (var tran = conn.Value.BeginTransaction())
78+
{
79+
writeToServer(tran);
80+
tran.Commit();
81+
}
82+
}
83+
}
84+
}
85+
else if (insert._transaction != null)
86+
{
87+
writeToServer(insert._transaction);
88+
}
89+
else if (insert._connection != null)
90+
{
91+
var isNotOpen = false;
92+
if (insert._connection.State != System.Data.ConnectionState.Open)
93+
{
94+
isNotOpen = true;
95+
insert._connection.Open();
96+
}
97+
try
98+
{
99+
using (var tran = insert._connection.BeginTransaction())
100+
{
101+
writeToServer(tran);
102+
tran.Commit();
103+
}
104+
}
105+
finally
106+
{
107+
if (isNotOpen)
108+
{
109+
insert._connection.Close();
110+
}
111+
}
112+
}
113+
else
114+
{
115+
throw new NotImplementedException($"ExecuteSqlBulkCopy {CoreErrorStrings.S_Not_Implemented_FeedBack}");
116+
}
117+
}
118+
finally
119+
{
120+
dt.Clear();
121+
}
122+
}
12123
}

0 commit comments

Comments
 (0)