Skip to content

Commit 03fe092

Browse files
2881028810
authored andcommitted
- 增加 EfCoreFluentApi HasData 设定 CodeFirst 种子数据;
- 完善 EfCoreFluentApi 功能测试; - 增加 DbContextOptions.NoneParameter 设置是否使用参数化执行 Insert/Update;
1 parent e5cbd40 commit 03fe092

File tree

18 files changed

+339
-78
lines changed

18 files changed

+339
-78
lines changed

Examples/efcore_to_freesql/Startup.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public Startup(IConfiguration configuration, ILoggerFactory loggerFactory)
2727
.UseAutoSyncStructure(true)
2828
.Build();
2929

30+
FreeSql.Extensions.EfCoreFluentApi.ICodeFirstExtensions.Test(Fsql);
31+
3032
DBContexts.BaseDBContext.Fsql = Fsql;
3133

3234
var sql11 = Fsql.Select<Topic1>().ToSql();
@@ -64,13 +66,20 @@ public Startup(IConfiguration configuration, ILoggerFactory loggerFactory)
6466

6567
public void ConfigureServices(IServiceCollection services)
6668
{
69+
services.AddControllersWithViews();
6770
services.AddSingleton<IFreeSql>(Fsql);
6871
services.AddMvc();
6972
}
7073

7174
public void Configure(IApplicationBuilder app)
7275
{
73-
app.UseDeveloperExceptionPage();
76+
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
77+
Console.OutputEncoding = Encoding.GetEncoding("GB2312");
78+
Console.InputEncoding = Encoding.GetEncoding("GB2312");
79+
80+
app.UseHttpMethodOverride(new HttpMethodOverrideOptions { FormFieldName = "X-Http-Method-Override" });
81+
app.UseDeveloperExceptionPage();
82+
app.UseRouting();
7483
app.UseEndpoints(a => a.MapControllers());
7584
}
7685
}

Examples/efcore_to_freesql/efcore_to_freesql.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
</ItemGroup>
1111

1212
<ItemGroup>
13+
<ProjectReference Include="..\..\Extensions\FreeSql.Extensions.EfCoreFluentApi\FreeSql.Extensions.EfCoreFluentApi.csproj" />
1314
<ProjectReference Include="..\..\FreeSql\FreeSql.csproj" />
15+
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Sqlite\FreeSql.Provider.Sqlite.csproj" />
1416
</ItemGroup>
1517

1618
</Project>

Extensions/FreeSql.Extensions.EfCoreFluentApi/EfCoreTableFluent.cs

Lines changed: 88 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Linq;
34
using System.Linq.Expressions;
45
using FreeSql.DataAnnotations;
56

67
namespace FreeSql.Extensions.EfCoreFluentApi
78
{
89
public class EfCoreTableFluent<T>
910
{
11+
IFreeSql _fsql;
1012
TableFluent<T> _tf;
11-
internal EfCoreTableFluent(TableFluent<T> tf)
13+
internal EfCoreTableFluent(IFreeSql fsql, TableFluent<T> tf)
1214
{
15+
_fsql = fsql;
1316
_tf = tf;
1417
}
1518

@@ -33,8 +36,10 @@ public EfCoreTableFluent<T> ToView(string name)
3336
#region HasKey
3437
public EfCoreTableFluent<T> HasKey(Expression<Func<T, object>> key)
3538
{
36-
if (key?.Body == null) return this;
37-
var exp = key.Body;
39+
var exp = key?.Body;
40+
if (exp?.NodeType == ExpressionType.Convert) exp = (exp as UnaryExpression)?.Operand;
41+
if (exp == null) throw new ArgumentException("参数错误 key 不能为 null");
42+
3843
switch (exp.NodeType)
3944
{
4045
case ExpressionType.MemberAccess:
@@ -52,8 +57,9 @@ public EfCoreTableFluent<T> HasKey(Expression<Func<T, object>> key)
5257
#region HasIndex
5358
public HasIndexFluent HasIndex(Expression<Func<T, object>> index)
5459
{
55-
if (index?.Body == null) throw new ArgumentException("参数错误 index 不能为 null");
56-
var exp = index.Body;
60+
var exp = index?.Body;
61+
if (exp?.NodeType == ExpressionType.Convert) exp = (exp as UnaryExpression)?.Operand;
62+
if (exp == null) throw new ArgumentException("参数错误 index 不能为 null");
5763

5864
var indexName = $"idx_{Guid.NewGuid().ToString("N").Substring(0, 8)}";
5965
var columns = new List<string>();
@@ -102,8 +108,9 @@ public HasIndexFluent HasName(string name)
102108
#region HasOne
103109
public HasOneFluent<T2> HasOne<T2>(Expression<Func<T, T2>> one)
104110
{
105-
if (one?.Body == null) throw new ArgumentException("参数错误 one 不能为 null");
106-
var exp = one.Body;
111+
var exp = one?.Body;
112+
if (exp?.NodeType == ExpressionType.Convert) exp = (exp as UnaryExpression)?.Operand;
113+
if (exp == null) throw new ArgumentException("参数错误 one 不能为 null");
107114

108115
var oneProperty = "";
109116
switch (exp.NodeType)
@@ -113,26 +120,29 @@ public HasOneFluent<T2> HasOne<T2>(Expression<Func<T, T2>> one)
113120
break;
114121
}
115122
if (string.IsNullOrEmpty(oneProperty)) throw new ArgumentException("参数错误 one");
116-
return new HasOneFluent<T2>(_tf, oneProperty);
123+
return new HasOneFluent<T2>(_fsql, _tf, oneProperty);
117124
}
118125
public class HasOneFluent<T2>
119126
{
127+
IFreeSql _fsql;
120128
TableFluent<T> _tf;
121129
string _selfProperty;
122130
string _selfBind;
123131
string _withManyProperty;
124132
string _withOneProperty;
125133
string _withOneBind;
126134

127-
internal HasOneFluent(TableFluent<T> modelBuilder, string oneProperty)
135+
internal HasOneFluent(IFreeSql fsql, TableFluent<T> modelBuilder, string oneProperty)
128136
{
137+
_fsql = fsql;
129138
_tf = modelBuilder;
130139
_selfProperty = oneProperty;
131140
}
132141
public HasOneFluent<T2> WithMany<TMany>(Expression<Func<T2, TMany>> many)
133142
{
134-
if (many?.Body == null) throw new ArgumentException("参数错误 many 不能为 null");
135-
var exp = many.Body;
143+
var exp = many?.Body;
144+
if (exp?.NodeType == ExpressionType.Convert) exp = (exp as UnaryExpression)?.Operand;
145+
if (exp == null) throw new ArgumentException("参数错误 many 不能为 null");
136146

137147
switch (exp.NodeType)
138148
{
@@ -142,13 +152,14 @@ public HasOneFluent<T2> WithMany<TMany>(Expression<Func<T2, TMany>> many)
142152
}
143153
if (string.IsNullOrEmpty(_withManyProperty)) throw new ArgumentException("参数错误 many");
144154
if (string.IsNullOrEmpty(_selfBind) == false)
145-
_tf.ConfigEntity<T2>(eb2 => eb2.Navigate(_withManyProperty, _selfBind));
155+
_fsql.CodeFirst.ConfigEntity<T2>(eb2 => eb2.Navigate(_withManyProperty, _selfBind));
146156
return this;
147157
}
148158
public HasOneFluent<T2> WithOne(Expression<Func<T2, T>> one, Expression<Func<T2, object>> foreignKey)
149159
{
150-
if (one?.Body == null) throw new ArgumentException("参数错误 one 不能为 null");
151-
var exp = one.Body;
160+
var exp = one?.Body;
161+
if (exp?.NodeType == ExpressionType.Convert) exp = (exp as UnaryExpression)?.Operand;
162+
if (exp == null) throw new ArgumentException("参数错误 one 不能为 null");
152163

153164
switch (exp.NodeType)
154165
{
@@ -158,8 +169,9 @@ public HasOneFluent<T2> WithOne(Expression<Func<T2, T>> one, Expression<Func<T2,
158169
}
159170
if (string.IsNullOrEmpty(_withOneProperty)) throw new ArgumentException("参数错误 one");
160171

161-
if (foreignKey?.Body == null) throw new ArgumentException("参数错误 foreignKey 不能为 null");
162-
exp = foreignKey.Body;
172+
exp = foreignKey?.Body;
173+
if (exp?.NodeType == ExpressionType.Convert) exp = (exp as UnaryExpression)?.Operand;
174+
if (exp == null) throw new ArgumentException("参数错误 foreignKey 不能为 null");
163175

164176
switch (exp.NodeType)
165177
{
@@ -176,13 +188,14 @@ public HasOneFluent<T2> WithOne(Expression<Func<T2, T>> one, Expression<Func<T2,
176188
}
177189
if (string.IsNullOrEmpty(_withOneBind)) throw new ArgumentException("参数错误 foreignKey");
178190
if (string.IsNullOrEmpty(_selfBind) == false)
179-
_tf.ConfigEntity<T2>(eb2 => eb2.Navigate(_withOneProperty, _withOneBind));
191+
_fsql.CodeFirst.ConfigEntity<T2>(eb2 => eb2.Navigate(_withOneProperty, _withOneBind));
180192
return this;
181193
}
182194
public HasOneFluent<T2> HasForeignKey(Expression<Func<T, object>> foreignKey)
183195
{
184-
if (foreignKey?.Body == null) throw new ArgumentException("参数错误 foreignKey 不能为 null");
185-
var exp = foreignKey.Body;
196+
var exp = foreignKey?.Body;
197+
if (exp?.NodeType == ExpressionType.Convert) exp = (exp as UnaryExpression)?.Operand;
198+
if (exp == null) throw new ArgumentException("参数错误 foreignKey 不能为 null");
186199

187200
switch (exp.NodeType)
188201
{
@@ -200,9 +213,9 @@ public HasOneFluent<T2> HasForeignKey(Expression<Func<T, object>> foreignKey)
200213
if (string.IsNullOrEmpty(_selfBind)) throw new ArgumentException("参数错误 foreignKey");
201214
_tf.Navigate(_selfProperty, _selfBind);
202215
if (string.IsNullOrEmpty(_withManyProperty) == false)
203-
_tf.ConfigEntity<T2>(eb2 => eb2.Navigate(_withManyProperty, _selfBind));
216+
_fsql.CodeFirst.ConfigEntity<T2>(eb2 => eb2.Navigate(_withManyProperty, _selfBind));
204217
if (string.IsNullOrEmpty(_withOneProperty) == false && string.IsNullOrEmpty(_withOneBind) == false)
205-
_tf.ConfigEntity<T2>(eb2 => eb2.Navigate(_withOneProperty, _withOneBind));
218+
_fsql.CodeFirst.ConfigEntity<T2>(eb2 => eb2.Navigate(_withOneProperty, _withOneBind));
206219
return this;
207220
}
208221
}
@@ -211,8 +224,9 @@ public HasOneFluent<T2> HasForeignKey(Expression<Func<T, object>> foreignKey)
211224
#region HasMany
212225
public HasManyFluent<T2> HasMany<T2>(Expression<Func<T, IEnumerable<T2>>> many)
213226
{
214-
if (many?.Body == null) throw new ArgumentException("参数错误 many 不能为 null");
215-
var exp = many.Body;
227+
var exp = many?.Body;
228+
if (exp?.NodeType == ExpressionType.Convert) exp = (exp as UnaryExpression)?.Operand;
229+
if (exp == null) throw new ArgumentException("参数错误 many 不能为 null");
216230

217231
var manyProperty = "";
218232
switch (exp.NodeType)
@@ -222,26 +236,29 @@ public HasManyFluent<T2> HasMany<T2>(Expression<Func<T, IEnumerable<T2>>> many)
222236
break;
223237
}
224238
if (string.IsNullOrEmpty(manyProperty)) throw new ArgumentException("参数错误 many");
225-
return new HasManyFluent<T2>(_tf, manyProperty);
239+
return new HasManyFluent<T2>(_fsql, _tf, manyProperty);
226240
}
227241
public class HasManyFluent<T2>
228242
{
243+
IFreeSql _fsql;
229244
TableFluent<T> _tf;
230245
string _selfProperty;
231246
string _selfBind;
232247
string _withOneProperty;
233248
string _withManyProperty;
234249

235-
internal HasManyFluent(TableFluent<T> modelBuilder, string manyProperty)
250+
internal HasManyFluent(IFreeSql fsql, TableFluent<T> modelBuilder, string manyProperty)
236251
{
252+
_fsql = fsql;
237253
_tf = modelBuilder;
238254
_selfProperty = manyProperty;
239255
}
240256

241257
public void WithMany(Expression<Func<T2, IEnumerable<T>>> many, Type middleType)
242258
{
243-
if (many?.Body == null) throw new ArgumentException("参数错误 many 不能为 null");
244-
var exp = many.Body;
259+
var exp = many?.Body;
260+
if (exp?.NodeType == ExpressionType.Convert) exp = (exp as UnaryExpression)?.Operand;
261+
if (exp == null) throw new ArgumentException("参数错误 many 不能为 null");
245262

246263
switch (exp.NodeType)
247264
{
@@ -252,12 +269,13 @@ public void WithMany(Expression<Func<T2, IEnumerable<T>>> many, Type middleType)
252269
if (string.IsNullOrEmpty(_withManyProperty)) throw new ArgumentException("参数错误 many");
253270

254271
_tf.Navigate(_selfProperty, null, middleType);
255-
_tf.ConfigEntity<T2>(eb2 => eb2.Navigate(_withManyProperty, null, middleType));
272+
_fsql.CodeFirst.ConfigEntity<T2>(eb2 => eb2.Navigate(_withManyProperty, null, middleType));
256273
}
257274
public HasManyFluent<T2> WithOne(Expression<Func<T2, T>> one)
258275
{
259-
if (one?.Body == null) throw new ArgumentException("参数错误 one 不能为 null");
260-
var exp = one.Body;
276+
var exp = one?.Body;
277+
if (exp?.NodeType == ExpressionType.Convert) exp = (exp as UnaryExpression)?.Operand;
278+
if (exp == null) throw new ArgumentException("参数错误 one 不能为 null");
261279

262280
switch (exp.NodeType)
263281
{
@@ -268,13 +286,14 @@ public HasManyFluent<T2> WithOne(Expression<Func<T2, T>> one)
268286
if (string.IsNullOrEmpty(_withOneProperty)) throw new ArgumentException("参数错误 one");
269287

270288
if (string.IsNullOrEmpty(_selfBind) == false)
271-
_tf.ConfigEntity<T2>(eb2 => eb2.Navigate(_withOneProperty, _selfBind));
289+
_fsql.CodeFirst.ConfigEntity<T2>(eb2 => eb2.Navigate(_withOneProperty, _selfBind));
272290
return this;
273291
}
274292
public HasManyFluent<T2> HasForeignKey(Expression<Func<T2, object>> foreignKey)
275293
{
276-
if (foreignKey?.Body == null) throw new ArgumentException("参数错误 foreignKey 不能为 null");
277-
var exp = foreignKey.Body;
294+
var exp = foreignKey?.Body;
295+
if (exp?.NodeType == ExpressionType.Convert) exp = (exp as UnaryExpression)?.Operand;
296+
if (exp == null) throw new ArgumentException("参数错误 foreignKey 不能为 null");
278297

279298
switch (exp.NodeType)
280299
{
@@ -292,7 +311,7 @@ public HasManyFluent<T2> HasForeignKey(Expression<Func<T2, object>> foreignKey)
292311
if (string.IsNullOrEmpty(_selfBind)) throw new ArgumentException("参数错误 foreignKey");
293312
_tf.Navigate(_selfProperty, _selfBind);
294313
if (string.IsNullOrEmpty(_withOneProperty) == false)
295-
_tf.ConfigEntity<T2>(eb2 => eb2.Navigate(_withOneProperty, _selfBind));
314+
_fsql.CodeFirst.ConfigEntity<T2>(eb2 => eb2.Navigate(_withOneProperty, _selfBind));
296315
return this;
297316
}
298317
}
@@ -303,10 +322,40 @@ public EfCoreTableFluent<T> Ignore<TProperty>(Expression<Func<T, TProperty>> pro
303322
_tf.Property(property).IsIgnore(true);
304323
return this;
305324
}
306-
//public EfCoreTableFluent<T> HasData(T data) => HasData(new[] { data });
307-
//public EfCoreTableFluent<T> HasData(IEnumerable<T> data)
308-
//{
309-
// return this;
310-
//}
325+
public EfCoreTableFluent<T> HasData(T data) => HasData(new[] { data });
326+
327+
/// <summary>
328+
/// 使用 Repository + EnableAddOrUpdateNavigateList + NoneParameter 方式插入种子数据
329+
/// </summary>
330+
/// <param name="data"></param>
331+
/// <returns></returns>
332+
public EfCoreTableFluent<T> HasData(IEnumerable<T> data)
333+
{
334+
if (data.Any() == false) return this;
335+
var sdCopy = data.Select(a => (object)a).ToList();
336+
var sdCopyLock = new object();
337+
_fsql.Aop.SyncStructureAfter += new EventHandler<Aop.SyncStructureAfterEventArgs>((s, e) =>
338+
{
339+
object[] sd = null;
340+
lock (sdCopyLock)
341+
sd = sdCopy?.ToArray();
342+
if (sd == null || sd.Any() == false) return;
343+
foreach (var et in e.EntityTypes)
344+
{
345+
if (et != typeof(T)) continue;
346+
if (_fsql.Select<object>().AsType(et).Any()) continue;
347+
348+
var repo = _fsql.GetRepository<object>();
349+
repo.DbContextOptions.EnableAddOrUpdateNavigateList = true;
350+
repo.DbContextOptions.NoneParameter = true;
351+
repo.AsType(et);
352+
repo.Insert(sd);
353+
354+
lock (sdCopyLock)
355+
sdCopy = null;
356+
}
357+
});
358+
return this;
359+
}
311360
}
312361
}

Extensions/FreeSql.Extensions.EfCoreFluentApi/FreeSql.Extensions.EfCoreFluentApi.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@
2525
<None Include="../../logo.png" Pack="true" PackagePath="\" />
2626
</ItemGroup>
2727

28+
<ItemGroup>
29+
<ProjectReference Include="..\..\FreeSql.DbContext\FreeSql.DbContext.csproj" />
30+
</ItemGroup>
31+
2832
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netstandard2.0|AnyCPU'">
2933
<DocumentationFile>FreeSql.Extensions.EfCoreFluentApi.xml</DocumentationFile>
3034
<WarningLevel>3</WarningLevel>
3135
</PropertyGroup>
32-
33-
<ItemGroup>
34-
<ProjectReference Include="..\..\FreeSql\FreeSql.csproj" />
35-
</ItemGroup>
3636

3737
</Project>

Extensions/FreeSql.Extensions.EfCoreFluentApi/FreeSql.Extensions.EfCoreFluentApi.xml

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)