diff --git a/apps/vue/src/components/Table/src/components/AdvancedSearch.vue b/apps/vue/src/components/Table/src/components/AdvancedSearch.vue
index a94768937..80241bfee 100644
--- a/apps/vue/src/components/Table/src/components/AdvancedSearch.vue
+++ b/apps/vue/src/components/Table/src/components/AdvancedSearch.vue
@@ -34,7 +34,7 @@
@@ -209,6 +209,14 @@
label: t('component.table.advancedSearch.notContains'),
value: DynamicComparison.NotContains,
},
+ {
+ label: t('component.table.advancedSearch.null'),
+ value: DynamicComparison.Null,
+ },
+ {
+ label: t('component.table.advancedSearch.notNull'),
+ value: DynamicComparison.NotNull,
+ },
]);
const getAvailableParams = computed(() => {
@@ -223,6 +231,23 @@
return defineParams.filter(dp => !formMdel.paramters.some(fp => fp.field === dp.name));
});
+ const getAvailableComparisonOptions = computed(() => {
+ return (paramter: DynamicParamter) => {
+ const defineParams = unref(defineParamsRef);
+ const defineParam = defineParams.find(p => p.name === paramter.field);
+ if (!defineParam) {
+ return comparisonOptions;
+ }
+ const availableComparator = defineParam.availableComparator ?? [];
+ if (availableComparator.length === 0) {
+ return comparisonOptions;
+ }
+ // 过滤可用比较符
+ return comparisonOptions
+ .filter(c => availableComparator.includes(c.value));
+ }
+ });
+
const filterOption = (input: string, option: any) => {
return option.description.toLowerCase().indexOf(input.toLowerCase()) >= 0;
};
diff --git a/apps/vue/src/components/Table/src/types/advancedSearch.ts b/apps/vue/src/components/Table/src/types/advancedSearch.ts
index 3a63abf5c..b06251301 100644
--- a/apps/vue/src/components/Table/src/types/advancedSearch.ts
+++ b/apps/vue/src/components/Table/src/types/advancedSearch.ts
@@ -30,6 +30,8 @@ export interface DefineParamter {
type: string;
/** 数据类型(js) */
javaScriptType: string;
+ /** 可用运算条件列表, 用于进一步约束字段可用比较符 */
+ availableComparator?: DynamicComparison[];
}
/** 连接条件 */
@@ -65,7 +67,11 @@ export enum DynamicComparison {
/** 包含 */
Contains = 10,
/** 不包含 */
- NotContains = 11
+ NotContains = 11,
+ /** 空 */
+ Null = 12,
+ /** 非空 */
+ NotNull = 12,
}
/** 动态查询字段 */
diff --git a/apps/vue/src/components/Table/src/types/table.ts b/apps/vue/src/components/Table/src/types/table.ts
index 4baf8fc29..443f71f06 100644
--- a/apps/vue/src/components/Table/src/types/table.ts
+++ b/apps/vue/src/components/Table/src/types/table.ts
@@ -1,8 +1,7 @@
import type { VNodeChild } from 'vue';
import type { PaginationProps } from './pagination';
import type { FormProps } from '/@/components/Form';
-import type { ColumnProps } from 'ant-design-vue/lib/table';
-import type { TableRowSelection as ITableRowSelection } from 'ant-design-vue/lib/table/interface';
+import type { TableRowSelection as ITableRowSelection, ColumnProps } from 'ant-design-vue/lib/table/interface';
import type { AdvanceSearchProps } from './advancedSearch';
import { ComponentType } from './componentType';
diff --git a/apps/vue/src/locales/lang/en/component.ts b/apps/vue/src/locales/lang/en/component.ts
index aaee986ab..bac3fd3e1 100644
--- a/apps/vue/src/locales/lang/en/component.ts
+++ b/apps/vue/src/locales/lang/en/component.ts
@@ -94,6 +94,8 @@ export default {
notEndsWith: 'Not Ends With',
contains: 'Contains',
notContains: 'Not Contains',
+ null: 'Null',
+ notNull: 'Not Null',
}
},
time: {
diff --git a/apps/vue/src/locales/lang/zh-CN/component.ts b/apps/vue/src/locales/lang/zh-CN/component.ts
index 207d457a5..483aaf82c 100644
--- a/apps/vue/src/locales/lang/zh-CN/component.ts
+++ b/apps/vue/src/locales/lang/zh-CN/component.ts
@@ -96,6 +96,8 @@ export default {
notEndsWith: '右不包含',
contains: '包含',
notContains: '不包含',
+ null: '空',
+ notNull: '非空',
}
},
time: {
diff --git a/aspnet-core/LINGYUN.MicroService.Common.sln b/aspnet-core/LINGYUN.MicroService.Common.sln
index b2d38253a..5e7eb96e1 100644
--- a/aspnet-core/LINGYUN.MicroService.Common.sln
+++ b/aspnet-core/LINGYUN.MicroService.Common.sln
@@ -286,13 +286,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TuiJuhe.Setting
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dynamic-queryable", "dynamic-queryable", "{3975D028-3672-4D23-BF77-B7F4A445D44E}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Linq.Dynamic.Queryable", "modules\dynamic-queryable\LINGYUN.Linq.Dynamic.Queryable\LINGYUN.Linq.Dynamic.Queryable.csproj", "{5512A359-80E8-440C-B652-7C96F614DD9E}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Linq.Dynamic.Queryable", "modules\dynamic-queryable\LINGYUN.Linq.Dynamic.Queryable\LINGYUN.Linq.Dynamic.Queryable.csproj", "{5512A359-80E8-440C-B652-7C96F614DD9E}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Dynamic.Queryable.Application.Contracts", "modules\dynamic-queryable\LINGYUN.Abp.Dynamic.Queryable.Application.Contracts\LINGYUN.Abp.Dynamic.Queryable.Application.Contracts.csproj", "{6A23EE81-0CA7-4CA7-859D-6ADB669DF0E1}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Dynamic.Queryable.Application.Contracts", "modules\dynamic-queryable\LINGYUN.Abp.Dynamic.Queryable.Application.Contracts\LINGYUN.Abp.Dynamic.Queryable.Application.Contracts.csproj", "{6A23EE81-0CA7-4CA7-859D-6ADB669DF0E1}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Dynamic.Queryable.Application", "modules\dynamic-queryable\LINGYUN.Abp.Dynamic.Queryable.Application\LINGYUN.Abp.Dynamic.Queryable.Application.csproj", "{EC7970DC-A656-46A7-9873-A730FE72B213}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Dynamic.Queryable.Application", "modules\dynamic-queryable\LINGYUN.Abp.Dynamic.Queryable.Application\LINGYUN.Abp.Dynamic.Queryable.Application.csproj", "{EC7970DC-A656-46A7-9873-A730FE72B213}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Dynamic.Queryable.HttpApi", "modules\dynamic-queryable\LINGYUN.Abp.Dynamic.Queryable.HttpApi\LINGYUN.Abp.Dynamic.Queryable.HttpApi.csproj", "{F515E8FA-449F-4D54-98A7-0F7DF1AA3C94}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Dynamic.Queryable.HttpApi", "modules\dynamic-queryable\LINGYUN.Abp.Dynamic.Queryable.HttpApi\LINGYUN.Abp.Dynamic.Queryable.HttpApi.csproj", "{F515E8FA-449F-4D54-98A7-0F7DF1AA3C94}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Linq.Dynamic.Queryable.Tests", "tests\LINGYUN.Linq.Dynamic.Queryable.Tests\LINGYUN.Linq.Dynamic.Queryable.Tests.csproj", "{E9AD81CA-D992-4F74-BD23-680CF98BE262}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.DynamicQueryable.EntityFrameworkCore.Tests", "tests\LINGYUN.Abp.DynamicQueryable.EntityFrameworkCore.Tests\LINGYUN.Abp.DynamicQueryable.EntityFrameworkCore.Tests.csproj", "{2E29FBF7-CECB-4DF9-9E02-5AFB704DDD10}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -760,6 +764,14 @@ Global
{F515E8FA-449F-4D54-98A7-0F7DF1AA3C94}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F515E8FA-449F-4D54-98A7-0F7DF1AA3C94}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F515E8FA-449F-4D54-98A7-0F7DF1AA3C94}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E9AD81CA-D992-4F74-BD23-680CF98BE262}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E9AD81CA-D992-4F74-BD23-680CF98BE262}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E9AD81CA-D992-4F74-BD23-680CF98BE262}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E9AD81CA-D992-4F74-BD23-680CF98BE262}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2E29FBF7-CECB-4DF9-9E02-5AFB704DDD10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2E29FBF7-CECB-4DF9-9E02-5AFB704DDD10}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2E29FBF7-CECB-4DF9-9E02-5AFB704DDD10}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2E29FBF7-CECB-4DF9-9E02-5AFB704DDD10}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -906,6 +918,8 @@ Global
{6A23EE81-0CA7-4CA7-859D-6ADB669DF0E1} = {3975D028-3672-4D23-BF77-B7F4A445D44E}
{EC7970DC-A656-46A7-9873-A730FE72B213} = {3975D028-3672-4D23-BF77-B7F4A445D44E}
{F515E8FA-449F-4D54-98A7-0F7DF1AA3C94} = {3975D028-3672-4D23-BF77-B7F4A445D44E}
+ {E9AD81CA-D992-4F74-BD23-680CF98BE262} = {B86C21A4-73B7-471E-B73A-B4B905EC9435}
+ {2E29FBF7-CECB-4DF9-9E02-5AFB704DDD10} = {B86C21A4-73B7-471E-B73A-B4B905EC9435}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {06C707C6-02C0-411A-AD3B-2D0E13787CB8}
diff --git a/aspnet-core/modules/dynamic-queryable/LINGYUN.Abp.Dynamic.Queryable.Application.Contracts/LINGYUN/Abp/Dynamic/Queryable/Dto/DynamicParamterDto.cs b/aspnet-core/modules/dynamic-queryable/LINGYUN.Abp.Dynamic.Queryable.Application.Contracts/LINGYUN/Abp/Dynamic/Queryable/Dto/DynamicParamterDto.cs
index 0f63b83c8..6e47b7edf 100644
--- a/aspnet-core/modules/dynamic-queryable/LINGYUN.Abp.Dynamic.Queryable.Application.Contracts/LINGYUN/Abp/Dynamic/Queryable/Dto/DynamicParamterDto.cs
+++ b/aspnet-core/modules/dynamic-queryable/LINGYUN.Abp.Dynamic.Queryable.Application.Contracts/LINGYUN/Abp/Dynamic/Queryable/Dto/DynamicParamterDto.cs
@@ -1,4 +1,6 @@
-namespace LINGYUN.Abp.Dynamic.Queryable;
+using LINGYUN.Linq.Dynamic.Queryable;
+
+namespace LINGYUN.Abp.Dynamic.Queryable;
public class DynamicParamterDto
{
@@ -6,4 +8,9 @@ public class DynamicParamterDto
public string Description { get; set; }
public string Type { get; set; }
public string JavaScriptType { get; set; }
+ public DynamicComparison[] AvailableComparator { get; set; }
+ public DynamicParamterDto()
+ {
+ AvailableComparator = new DynamicComparison[0];
+ }
}
diff --git a/aspnet-core/modules/dynamic-queryable/LINGYUN.Abp.Dynamic.Queryable.Application/LINGYUN/Abp/Dynamic/Queryable/DynamicQueryableAppService.cs b/aspnet-core/modules/dynamic-queryable/LINGYUN.Abp.Dynamic.Queryable.Application/LINGYUN/Abp/Dynamic/Queryable/DynamicQueryableAppService.cs
index 263e52643..93a885c39 100644
--- a/aspnet-core/modules/dynamic-queryable/LINGYUN.Abp.Dynamic.Queryable.Application/LINGYUN/Abp/Dynamic/Queryable/DynamicQueryableAppService.cs
+++ b/aspnet-core/modules/dynamic-queryable/LINGYUN.Abp.Dynamic.Queryable.Application/LINGYUN/Abp/Dynamic/Queryable/DynamicQueryableAppService.cs
@@ -1,4 +1,5 @@
-using Microsoft.Extensions.Options;
+using LINGYUN.Linq.Dynamic.Queryable;
+using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -32,13 +33,15 @@ public abstract class DynamicQueryableAppService : Applicat
// 字段本地化描述规则
// 在本地化文件中定义 DisplayName:PropertyName
var localizedProp = L[$"DisplayName:{propertyInfo.Name}"];
+ var propertyTypeMap = GetPropertyTypeMap(propertyInfo.PropertyType);
dynamicParamters.Add(
new DynamicParamterDto
{
Name = propertyInfo.Name,
Type = propertyInfo.PropertyType.FullName,
Description = localizedProp.Value ?? propertyInfo.Name,
- JavaScriptType = ConvertToJavaScriptType(propertyInfo.PropertyType)
+ JavaScriptType = propertyTypeMap.JavaScriptType,
+ AvailableComparator = propertyTypeMap.AvailableComparator
});
}
@@ -74,10 +77,13 @@ public abstract class DynamicQueryableAppService : Applicat
return ObjectMapper.Map, List>(entities);
}
- protected virtual string ConvertToJavaScriptType(Type propertyType)
+ protected virtual (string JavaScriptType, DynamicComparison[] AvailableComparator) GetPropertyTypeMap(Type propertyType)
{
+ var isNullableType = false;
+ var availableComparator = new List();
if (propertyType.IsNullableType())
{
+ isNullableType = true;
propertyType = propertyType.GetGenericArguments().FirstOrDefault();
}
var typeCode = Type.GetTypeCode(propertyType);
@@ -94,27 +100,103 @@ public abstract class DynamicQueryableAppService : Applicat
case TypeCode.Double:
case TypeCode.SByte:
case TypeCode.Decimal:
- return "number";
+ // 数值类型只支持如下操作符
+ // 小于、小于等于、大于、大于等于、等于、不等于、空、非空
+ availableComparator.AddRange(new[]
+ {
+ DynamicComparison.GreaterThan,
+ DynamicComparison.GreaterThanOrEqual,
+ DynamicComparison.LessThan,
+ DynamicComparison.LessThanOrEqual,
+ DynamicComparison.Equal,
+ DynamicComparison.NotEqual,
+ });
+ if (isNullableType)
+ {
+ availableComparator.AddRange(new []
+ {
+ DynamicComparison.Null,
+ DynamicComparison.NotNull
+ });
+ }
+ return ("number", availableComparator.ToArray());
case TypeCode.Boolean:
- return "boolean";
+ // 布尔类型只支持如下操作符
+ // 等于、不等于、空、非空
+ availableComparator.AddRange(new[]
+ {
+ DynamicComparison.Equal,
+ DynamicComparison.NotEqual,
+ });
+ if (isNullableType)
+ {
+ availableComparator.AddRange(new[]
+ {
+ DynamicComparison.Null,
+ DynamicComparison.NotNull
+ });
+ }
+ return ("boolean", availableComparator.ToArray());
case TypeCode.Char:
case TypeCode.String:
- return "string";
+ // 字符类型支持所有操作符
+ return ("string", availableComparator.ToArray());
case TypeCode.DateTime:
- return "Date";
+ // 时间类型只支持如下操作符
+ // 小于、小于等于、大于、大于等于、等于、不等于、空、非空
+ availableComparator.AddRange(new[]
+ {
+ DynamicComparison.GreaterThan,
+ DynamicComparison.GreaterThanOrEqual,
+ DynamicComparison.LessThan,
+ DynamicComparison.LessThanOrEqual,
+ DynamicComparison.Equal,
+ DynamicComparison.NotEqual,
+ });
+ if (isNullableType)
+ {
+ availableComparator.AddRange(new[]
+ {
+ DynamicComparison.Null,
+ DynamicComparison.NotNull
+ });
+ }
+ return ("Date", availableComparator.ToArray());
+ default:
case TypeCode.Object:
+ case TypeCode.Empty:
+ case TypeCode.DBNull:
+ if (isNullableType)
+ {
+ availableComparator.AddRange(new[]
+ {
+ DynamicComparison.Null,
+ DynamicComparison.NotNull
+ });
+ }
if (propertyType.IsArray)
{
- return "array";
+ // 数组类型只支持如下操作符
+ // 包含、不包含、空、非空
+ availableComparator.AddRange(new[]
+ {
+ DynamicComparison.Contains,
+ DynamicComparison.NotContains,
+ });
+
+ return ("array", availableComparator.ToArray());
}
else
{
- return "object";
+ // 未知对象类型只支持如下操作符
+ // 等于、不等于、空、非空
+ availableComparator.AddRange(new[]
+ {
+ DynamicComparison.Equal,
+ DynamicComparison.NotEqual,
+ });
+ return ("object", availableComparator.ToArray());
}
- default:
- case TypeCode.Empty:
- case TypeCode.DBNull:
- return "object";
}
}
}
diff --git a/aspnet-core/modules/dynamic-queryable/LINGYUN.Linq.Dynamic.Queryable/LINGYUN.Linq.Dynamic.Queryable.csproj b/aspnet-core/modules/dynamic-queryable/LINGYUN.Linq.Dynamic.Queryable/LINGYUN.Linq.Dynamic.Queryable.csproj
index 7128b5214..6a04a7f20 100644
--- a/aspnet-core/modules/dynamic-queryable/LINGYUN.Linq.Dynamic.Queryable/LINGYUN.Linq.Dynamic.Queryable.csproj
+++ b/aspnet-core/modules/dynamic-queryable/LINGYUN.Linq.Dynamic.Queryable/LINGYUN.Linq.Dynamic.Queryable.csproj
@@ -8,4 +8,9 @@
+
+
+
+
+
diff --git a/aspnet-core/modules/dynamic-queryable/LINGYUN.Linq.Dynamic.Queryable/LINGYUN/Linq/Dynamic/Queryable/DynamicComparison.cs b/aspnet-core/modules/dynamic-queryable/LINGYUN.Linq.Dynamic.Queryable/LINGYUN/Linq/Dynamic/Queryable/DynamicComparison.cs
index 84f343b42..99e7f80f6 100644
--- a/aspnet-core/modules/dynamic-queryable/LINGYUN.Linq.Dynamic.Queryable/LINGYUN/Linq/Dynamic/Queryable/DynamicComparison.cs
+++ b/aspnet-core/modules/dynamic-queryable/LINGYUN.Linq.Dynamic.Queryable/LINGYUN/Linq/Dynamic/Queryable/DynamicComparison.cs
@@ -48,6 +48,14 @@ public enum DynamicComparison
///
/// 不包含
///
- NotContains = 11
+ NotContains = 11,
+ ///
+ /// 空值
+ ///
+ Null = 12,
+ ///
+ /// 非空
+ ///
+ NotNull = 13
}
diff --git a/aspnet-core/modules/dynamic-queryable/LINGYUN.Linq.Dynamic.Queryable/LINGYUN/Linq/Dynamic/Queryable/DynamicParamter.cs b/aspnet-core/modules/dynamic-queryable/LINGYUN.Linq.Dynamic.Queryable/LINGYUN/Linq/Dynamic/Queryable/DynamicParamter.cs
index 1ac103d17..14d4c6454 100644
--- a/aspnet-core/modules/dynamic-queryable/LINGYUN.Linq.Dynamic.Queryable/LINGYUN/Linq/Dynamic/Queryable/DynamicParamter.cs
+++ b/aspnet-core/modules/dynamic-queryable/LINGYUN.Linq.Dynamic.Queryable/LINGYUN/Linq/Dynamic/Queryable/DynamicParamter.cs
@@ -1,7 +1,12 @@
-namespace LINGYUN.Linq.Dynamic.Queryable;
+using JetBrains.Annotations;
+using System.ComponentModel.DataAnnotations;
+
+namespace LINGYUN.Linq.Dynamic.Queryable;
public class DynamicParamter
{
+ [NotNull]
+ [Required]
public string Field { get; set; }
public DynamicLogic Logic { get; set; } = DynamicLogic.And;
@@ -9,5 +14,6 @@ public class DynamicParamter
public DynamicComparison Comparison { get; set; } = DynamicComparison.Equal;
public object Value { get; set; }
+
public string Type { get; set; }
}
diff --git a/aspnet-core/modules/dynamic-queryable/LINGYUN.Linq.Dynamic.Queryable/System/Linq/Expressions/ObjectQueryableExtensions.cs b/aspnet-core/modules/dynamic-queryable/LINGYUN.Linq.Dynamic.Queryable/System/Linq/Expressions/ObjectQueryableExtensions.cs
index d23ae7a0e..9334c1123 100644
--- a/aspnet-core/modules/dynamic-queryable/LINGYUN.Linq.Dynamic.Queryable/System/Linq/Expressions/ObjectQueryableExtensions.cs
+++ b/aspnet-core/modules/dynamic-queryable/LINGYUN.Linq.Dynamic.Queryable/System/Linq/Expressions/ObjectQueryableExtensions.cs
@@ -34,65 +34,213 @@ public static class ObjectQueryableExtensions
{
propertyType = (leftParamter.Member as PropertyInfo)?.PropertyType ?? paramter.Value.GetType();
}
- var rightParamter = Expression.Convert(Expression.Constant(paramter.Value), propertyType);
switch (paramter.Comparison)
{
- case DynamicComparison.Equal:
- exp = Expression.Equal(leftParamter, rightParamter);
- break;
case DynamicComparison.NotEqual:
- exp = Expression.NotEqual(leftParamter, rightParamter);
+ // For example(MySql):
+ // ...Other (Field <> Value)
+ exp = Expression.NotEqual(
+ leftParamter,
+ Expression.Convert(Expression.Constant(paramter.Value), propertyType));
break;
case DynamicComparison.LessThan:
- exp = Expression.LessThan(leftParamter, rightParamter);
+ // For example(MySql):
+ // ...Other (Field < Value)
+ exp = Expression.LessThan(
+ leftParamter,
+ Expression.Convert(Expression.Constant(paramter.Value), propertyType));
break;
case DynamicComparison.LessThanOrEqual:
- exp = Expression.LessThanOrEqual(leftParamter, rightParamter);
+ // For example(MySql):
+ // ...Other (Field <= Value)
+
+ exp = Expression.LessThanOrEqual(
+ leftParamter,
+ Expression.Convert(Expression.Constant(paramter.Value), propertyType));
break;
case DynamicComparison.GreaterThan:
- exp = Expression.GreaterThan(leftParamter, rightParamter);
+ // For example(MySql):
+ // ...Other (Field > Value)
+ exp = Expression.GreaterThan(
+ leftParamter,
+ Expression.Convert(Expression.Constant(paramter.Value), propertyType));
break;
case DynamicComparison.GreaterThanOrEqual:
- exp = Expression.GreaterThanOrEqual(leftParamter, rightParamter);
+ // For example(MySql):
+ // ...Other (Field >= Value)
+
+ exp = Expression.GreaterThanOrEqual(
+ leftParamter,
+ Expression.Convert(Expression.Constant(paramter.Value), propertyType));
break;
case DynamicComparison.StartsWith:
+ // For example(MySql):
+ // ...Other And Field LIKE 'Value%'
exp = Expression.Call(
leftParamter,
typeof(string).GetMethod(nameof(String.StartsWith), new[] { typeof(string) }),
- rightParamter);
+ Expression.Convert(Expression.Constant(paramter.Value), propertyType));
+
+ // TODO: 单元测试通过
+ // For example(MySql):
+ // ...Other ((Field IS NOT NULL) AND (Field LIKE 'Value%'))
+ //var startsWithNotNullExp = Expression.Not(
+ // Expression.Equal(leftParamter,
+ // Expression.Convert(
+ // Expression.Constant(null), propertyType)));
+
+ //var startsWithExp = Expression.Call(
+ // leftParamter,
+ // typeof(string).GetMethod(nameof(String.StartsWith), new[] { typeof(string) }),
+ // rightParamter);
+
+ //exp = Expression.AndAlso(startsWithNotNullExp, startsWithExp);
+
break;
case DynamicComparison.NotStartsWith:
+ // For example(MySql):
+ // ...Other NOT Field LIKE 'Value%'
+
exp = Expression.Not(
Expression.Call(
leftParamter,
typeof(string).GetMethod(nameof(String.StartsWith), new[] { typeof(string) }),
- rightParamter));
+ Expression.Convert(Expression.Constant(paramter.Value), propertyType)));
+
+ // TODO: 单元测试通过
+ // For example(MySql):
+ // ...Other ((Field IS NULL) OR NOT (Field LIKE 'Value%'))
+ //var notStartsWithNullExp = Expression.Equal(leftParamter,
+ // Expression.Convert(
+ // Expression.Constant(null), propertyType));
+
+ //var notStartsWithExp = Expression.Not(
+ // Expression.Call(
+ // leftParamter,
+ // typeof(string).GetMethod(nameof(String.StartsWith), new[] { typeof(string) }),
+ // rightParamter));
+
+ //exp = Expression.OrElse(notStartsWithNullExp, notStartsWithExp);
break;
case DynamicComparison.EndsWith:
+ // For example(MySql):
+ // ...Other AND Field LIKE '%Value'
exp = Expression.Call(
leftParamter,
typeof(string).GetMethod(nameof(String.EndsWith), new[] { typeof(string) }),
- rightParamter);
+ Expression.Convert(Expression.Constant(paramter.Value), propertyType));
+
+ // TODO: 单元测试通过
+ // For example(MySql):
+ // ...Other ((Field IS NOT NULL) AND (Field LIKE '%Value'))
+ //var endsWithNotNullExp = Expression.Not(
+ // Expression.Equal(leftParamter,
+ // Expression.Convert(
+ // Expression.Constant(null), propertyType)));
+
+ //var endsWithExp = Expression.Call(
+ // leftParamter,
+ // typeof(string).GetMethod(nameof(String.EndsWith), new[] { typeof(string) }),
+ // rightParamter);
+
+ //exp = Expression.AndAlso(endsWithNotNullExp, endsWithExp);
break;
case DynamicComparison.NotEndsWith:
+ // For example(MySql):
+ // ...Other NOT (Field LIKE '%Value')
exp = Expression.Not(
Expression.Call(
leftParamter,
typeof(string).GetMethod(nameof(String.EndsWith), new[] { typeof(string) }),
- rightParamter));
+ Expression.Convert(Expression.Constant(paramter.Value), propertyType)));
+
+ // TODO: 单元测试通过
+ // For example(MySql):
+ // ...Other ((Field IS NULL) OR NOT (Field LIKE '%Value'))
+ //var notEndsWithNullExp = Expression.Equal(leftParamter,
+ // Expression.Convert(
+ // Expression.Constant(null), propertyType));
+
+ //var notEndsWithExp = Expression.Not(
+ // Expression.Call(
+ // leftParamter,
+ // typeof(string).GetMethod(nameof(String.EndsWith), new[] { typeof(string) }),
+ // rightParamter));
+
+ //exp = Expression.OrElse(notEndsWithNullExp, notEndsWithExp);
break;
case DynamicComparison.Contains:
+ // For example(MySql):
+ // ...Other AND (Field LIKE '%Value%')
exp = Expression.Call(
leftParamter,
typeof(string).GetMethod(nameof(String.Contains), new[] { typeof(string) }),
- rightParamter);
+ Expression.Convert(Expression.Constant(paramter.Value), propertyType));
+
+ // TODO: 单元测试通过
+ // For example(MySql):
+ // ...Other ((Field IS NOT NULL) AND (Field LIKE '%Value%'))
+ //var containsNotNullExp = Expression.Not(
+ // Expression.Equal(leftParamter,
+ // Expression.Convert(
+ // Expression.Constant(null), propertyType)));
+
+ //var containsExp = Expression.Call(
+ // leftParamter,
+ // typeof(string).GetMethod(nameof(String.Contains), new[] { typeof(string) }),
+ // rightParamter);
+
+ //exp = Expression.AndAlso(containsNotNullExp, containsExp);
break;
case DynamicComparison.NotContains:
+ // For example(MySql):
+ // ...Other AND (Field NOT LIKE '%Value%')
exp = Expression.Not(
- Expression.Call(
- leftParamter,
- typeof(string).GetMethod(nameof(String.Contains), new[] { typeof(string) }),
- rightParamter));
+ Expression.Call(
+ leftParamter,
+ typeof(string).GetMethod(nameof(String.Contains), new[] { typeof(string) }),
+ Expression.Convert(Expression.Constant(paramter.Value), propertyType)));
+ // TODO: 单元测试通过
+ // For example(MySql):
+ // ...Other ((Field IS NULL) OR (Field NOT LIKE '%Value%'))
+
+ //var notContainsNullExp = Expression.Equal(leftParamter,
+ // Expression.Convert(
+ // Expression.Constant(null), propertyType));
+
+ //var notContainsExp = Expression.Not(
+ // Expression.Call(
+ // leftParamter,
+ // typeof(string).GetMethod(nameof(String.Contains), new[] { typeof(string) }),
+ // rightParamter));
+
+ //exp = Expression.OrElse(notContainsNullExp, notContainsExp);
+ break;
+ case DynamicComparison.Null:
+ // For example(MySql):
+ // ...Other (Field IS NULL)
+
+ // 非空字段设定为比对默认值
+ exp = Expression.Equal(leftParamter,
+ Expression.Convert(
+ Expression.Constant(GetDefaultValue(propertyType)), propertyType));
+ break;
+ case DynamicComparison.NotNull:
+ // For example(MySql):
+ // ...Other (Field IS NOT NULL)
+
+ exp = Expression.NotEqual(leftParamter,
+ Expression.Convert(
+ Expression.Constant(GetDefaultValue(propertyType)), propertyType));
+ break;
+ default:
+ case DynamicComparison.Equal:
+ // For example(MySql):
+ // ...Other (Field = Value)
+
+ exp = Expression.Equal(
+ leftParamter,
+ Expression.Convert(Expression.Constant(paramter.Value), propertyType));
break;
}
expressions.Push(exp);
@@ -104,16 +252,27 @@ public static class ObjectQueryableExtensions
switch (paramter.Logic)
{
- case DynamicLogic.And:
- expressions.Push(Expression.AndAlso(exp1, exp2));
- break;
case DynamicLogic.Or:
expressions.Push(Expression.Or(exp1, exp2));
break;
+ default:
+ case DynamicLogic.And:
+ expressions.Push(Expression.AndAlso(exp1, exp2));
+ break;
}
}
}
return Expression.Lambda(expressions.Pop(), condition.Parameters.ToArray());
}
+
+ private static object GetDefaultValue(Type type)
+ {
+ // TODO: 非空字段此处返回默认值
+ if (type.IsNullableType())
+ {
+ return null;
+ }
+ return type.IsValueType ? Activator.CreateInstance(type) : null;
+ }
}
diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application/LINGYUN/Abp/TaskManagement/BackgroundJobInfoAppService.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application/LINGYUN/Abp/TaskManagement/BackgroundJobInfoAppService.cs
index bc27d1714..ed377a1fe 100644
--- a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application/LINGYUN/Abp/TaskManagement/BackgroundJobInfoAppService.cs
+++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application/LINGYUN/Abp/TaskManagement/BackgroundJobInfoAppService.cs
@@ -374,9 +374,13 @@ public class BackgroundJobInfoAppService : DynamicQueryableAppService
+
+
+ net6.0
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/tests/LINGYUN.Abp.DynamicQueryable.EntityFrameworkCore.Tests/LINGYUN/Abp/DynamicQueryable/EntityFrameworkCore/AbpDynamicQueryableEntityFrameworkCoreTestBase.cs b/aspnet-core/tests/LINGYUN.Abp.DynamicQueryable.EntityFrameworkCore.Tests/LINGYUN/Abp/DynamicQueryable/EntityFrameworkCore/AbpDynamicQueryableEntityFrameworkCoreTestBase.cs
new file mode 100644
index 000000000..c68022c75
--- /dev/null
+++ b/aspnet-core/tests/LINGYUN.Abp.DynamicQueryable.EntityFrameworkCore.Tests/LINGYUN/Abp/DynamicQueryable/EntityFrameworkCore/AbpDynamicQueryableEntityFrameworkCoreTestBase.cs
@@ -0,0 +1,4 @@
+namespace LINGYUN.Abp.DynamicQueryable.EntityFrameworkCore;
+public abstract class AbpDynamicQueryableEntityFrameworkCoreTestBase : AbpTestsBase
+{
+}
diff --git a/aspnet-core/tests/LINGYUN.Abp.DynamicQueryable.EntityFrameworkCore.Tests/LINGYUN/Abp/DynamicQueryable/EntityFrameworkCore/AbpDynamicQueryableEntityFrameworkCoreTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.DynamicQueryable.EntityFrameworkCore.Tests/LINGYUN/Abp/DynamicQueryable/EntityFrameworkCore/AbpDynamicQueryableEntityFrameworkCoreTestModule.cs
new file mode 100644
index 000000000..7e9fa10a5
--- /dev/null
+++ b/aspnet-core/tests/LINGYUN.Abp.DynamicQueryable.EntityFrameworkCore.Tests/LINGYUN/Abp/DynamicQueryable/EntityFrameworkCore/AbpDynamicQueryableEntityFrameworkCoreTestModule.cs
@@ -0,0 +1,9 @@
+using Volo.Abp.Modularity;
+
+namespace LINGYUN.Abp.DynamicQueryable.EntityFrameworkCore;
+
+[DependsOn(typeof(AbpEntityFrameworkCoreTestModule))]
+public class AbpDynamicQueryableEntityFrameworkCoreTestModule : AbpModule
+{
+
+}
\ No newline at end of file
diff --git a/aspnet-core/tests/LINGYUN.Abp.DynamicQueryable.EntityFrameworkCore.Tests/LINGYUN/Abp/DynamicQueryable/EntityFrameworkCore/DynamicQueryableEntityFrameworkCoreTests.cs b/aspnet-core/tests/LINGYUN.Abp.DynamicQueryable.EntityFrameworkCore.Tests/LINGYUN/Abp/DynamicQueryable/EntityFrameworkCore/DynamicQueryableEntityFrameworkCoreTests.cs
new file mode 100644
index 000000000..f0a53cb7a
--- /dev/null
+++ b/aspnet-core/tests/LINGYUN.Abp.DynamicQueryable.EntityFrameworkCore.Tests/LINGYUN/Abp/DynamicQueryable/EntityFrameworkCore/DynamicQueryableEntityFrameworkCoreTests.cs
@@ -0,0 +1,302 @@
+using LINGYUN.Abp.EntityFrameworkCore;
+using System;
+using System.Linq;
+using System.Linq.Expressions;
+using ExecDynamicQueryable = LINGYUN.Linq.Dynamic.Queryable.DynamicQueryable;
+
+namespace LINGYUN.Abp.DynamicQueryable.EntityFrameworkCore;
+
+public class DynamicQueryableEntityFrameworkCoreTests : AbpDynamicQueryableEntityFrameworkCoreTestBase
+{
+ [Fact]
+ public void Should_Null()
+ {
+ using var dbContext = GetRequiredService();
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new ExecDynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.Null,
+ Field = nameof(EfCoreTestEntity.PropString),
+ Logic = DynamicLogic.And
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = dbContext.TestEntities.Local.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(2);
+ }
+
+ [Fact]
+ public void Should_Not_Null()
+ {
+ using var dbContext = GetRequiredService();
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new ExecDynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.NotNull,
+ Field = nameof(EfCoreTestEntity.PropString),
+ Logic = DynamicLogic.And
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = dbContext.TestEntities.Local.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(2);
+ }
+
+ [Fact]
+ public void Should_Equal()
+ {
+ using var dbContext = GetRequiredService();
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new ExecDynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.Equal,
+ Field = nameof(EfCoreTestEntity.PropInt32),
+ Logic = DynamicLogic.And,
+ Value = 2048
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = dbContext.TestEntities.Local.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(1);
+ }
+
+ [Fact]
+ public void Should_Not_Equal()
+ {
+ using var dbContext = GetRequiredService();
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new ExecDynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.NotEqual,
+ Field = nameof(EfCoreTestEntity.PropInt32),
+ Logic = DynamicLogic.And,
+ Value = null
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = dbContext.TestEntities.Local.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(2);
+ }
+
+ [Fact]
+ public void Should_Less_Than()
+ {
+ using var dbContext = GetRequiredService();
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new ExecDynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.LessThan,
+ Field = nameof(EfCoreTestEntity.PropInt32),
+ Logic = DynamicLogic.And,
+ Value = 2048
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = dbContext.TestEntities.Local.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(1);
+ }
+
+ [Fact]
+ public void Should_Less_Than_Or_Equal()
+ {
+ using var dbContext = GetRequiredService();
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new ExecDynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.LessThanOrEqual,
+ Field = nameof(EfCoreTestEntity.PropInt32),
+ Logic = DynamicLogic.And,
+ Value = 2048
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = dbContext.TestEntities.Local.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(2);
+ }
+
+ [Fact]
+ public void Should_Greater_Than()
+ {
+ using var dbContext = GetRequiredService();
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new ExecDynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.GreaterThan,
+ Field = nameof(EfCoreTestEntity.PropInt64),
+ Logic = DynamicLogic.And,
+ Value = 1024L
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = dbContext.TestEntities.Local.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(2);
+ }
+
+ [Fact]
+ public void Should_Greater_Than_Or_Equal()
+ {
+ using var dbContext = GetRequiredService();
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new ExecDynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.GreaterThanOrEqual,
+ Field = nameof(EfCoreTestEntity.PropInt64),
+ Logic = DynamicLogic.And,
+ Value = 1024L
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = dbContext.TestEntities.Local.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(3);
+ }
+
+ [Fact]
+ public void Should_Starts_With()
+ {
+ using var dbContext = GetRequiredService();
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new ExecDynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.StartsWith,
+ Field = nameof(EfCoreTestEntity.PropString),
+ Logic = DynamicLogic.And,
+ Value = "1"
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = dbContext.TestEntities.Local.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(1);
+ }
+
+ [Fact]
+ public void Should_Not_Starts_With()
+ {
+ using var dbContext = GetRequiredService();
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new ExecDynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.NotStartsWith,
+ Field = nameof(EfCoreTestEntity.PropString),
+ Logic = DynamicLogic.And,
+ Value = "1"
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = dbContext.TestEntities.Local.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(3);
+ }
+
+ [Fact]
+ public void Should_Ends_With()
+ {
+ using var dbContext = GetRequiredService();
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new ExecDynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.EndsWith,
+ Field = nameof(EfCoreTestEntity.PropString),
+ Logic = DynamicLogic.And,
+ Value = "1"
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = dbContext.TestEntities.Local.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(1);
+ }
+
+ [Fact]
+ public void Should_Not_Ends_With()
+ {
+ using var dbContext = GetRequiredService();
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new ExecDynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.NotEndsWith,
+ Field = nameof(EfCoreTestEntity.PropString),
+ Logic = DynamicLogic.And,
+ Value = "1"
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = dbContext.TestEntities.Local.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(3);
+ }
+
+ [Fact]
+ public void Should_Contains()
+ {
+ using var dbContext = GetRequiredService();
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new ExecDynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.Contains,
+ Field = nameof(EfCoreTestEntity.PropString),
+ Logic = DynamicLogic.And,
+ Value = "22"
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = dbContext.TestEntities.Local.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(2);
+ }
+
+ [Fact]
+ public void Should_Not_Contains()
+ {
+ using var dbContext = GetRequiredService();
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new ExecDynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.NotContains,
+ Field = nameof(EfCoreTestEntity.PropString),
+ Logic = DynamicLogic.And,
+ Value = "23"
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = dbContext.TestEntities.Local.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(3);
+ }
+}
diff --git a/aspnet-core/tests/LINGYUN.Abp.DynamicQueryable.EntityFrameworkCore.Tests/Usings.cs b/aspnet-core/tests/LINGYUN.Abp.DynamicQueryable.EntityFrameworkCore.Tests/Usings.cs
new file mode 100644
index 000000000..c649add73
--- /dev/null
+++ b/aspnet-core/tests/LINGYUN.Abp.DynamicQueryable.EntityFrameworkCore.Tests/Usings.cs
@@ -0,0 +1,5 @@
+global using Xunit;
+global using Shouldly;
+global using LINGYUN.Abp.EntityFrameworkCore.Tests;
+global using LINGYUN.Abp.Tests;
+global using LINGYUN.Linq.Dynamic.Queryable;
diff --git a/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN.Abp.EntityFrameworkCore.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN.Abp.EntityFrameworkCore.Tests.csproj
index a4a511315..d7bd553f1 100644
--- a/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN.Abp.EntityFrameworkCore.Tests.csproj
+++ b/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN.Abp.EntityFrameworkCore.Tests.csproj
@@ -1,4 +1,4 @@
-
+
net6.0
diff --git a/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs
index cf6b484e4..418c73dc2 100644
--- a/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs
+++ b/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs
@@ -4,6 +4,7 @@ using Microsoft.Extensions.DependencyInjection;
using System;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Modularity;
+using Volo.Abp.Threading;
using Volo.Abp.Uow;
namespace LINGYUN.Abp.EntityFrameworkCore.Tests
@@ -13,9 +14,22 @@ namespace LINGYUN.Abp.EntityFrameworkCore.Tests
)]
public class AbpEntityFrameworkCoreTestModule : AbpModule
{
+ //private string _testDbFile = "./abp-ef-test-db.db";
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddEntityFrameworkInMemoryDatabase();
+ //var connectionString = $"Data Source={_testDbFile}";
+
+ //var sqliteConnection = CreateDatabaseAndGetConnection(connectionString);
+
+ var memoryDbName = Guid.NewGuid().ToString();
+
+ var dbConetxt = CreateDatabaseAndGetDbContext(memoryDbName);
+
+ AsyncHelper.RunSync(async () =>
+ await new EfCoreTestEntityDataSeeder(dbConetxt).SeedAsync());
+
+ context.Services.AddSingleton(dbConetxt);
var databaseName = Guid.NewGuid().ToString();
@@ -27,7 +41,7 @@ namespace LINGYUN.Abp.EntityFrameworkCore.Tests
abpDbContextConfigurationContext.DbContextOptions.EnableSensitiveDataLogging();
abpDbContextConfigurationContext.DbContextOptions.UseEFCoreLogger();
- abpDbContextConfigurationContext.DbContextOptions.UseInMemoryDatabase(databaseName);
+ abpDbContextConfigurationContext.DbContextOptions.UseInMemoryDatabase(memoryDbName);
});
});
@@ -36,5 +50,12 @@ namespace LINGYUN.Abp.EntityFrameworkCore.Tests
options.TransactionBehavior = UnitOfWorkTransactionBehavior.Disabled; //EF in-memory database does not support transactions
});
}
+
+ private EfCoreTestDbContext CreateDatabaseAndGetDbContext(string dbName)
+ {
+ return new EfCoreTestDbContext(
+ new DbContextOptionsBuilder().UseInMemoryDatabase(dbName).Options
+ );
+ }
}
}
diff --git a/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/EfCoreTestDbContext.cs b/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/EfCoreTestDbContext.cs
new file mode 100644
index 000000000..023d428f8
--- /dev/null
+++ b/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/EfCoreTestDbContext.cs
@@ -0,0 +1,24 @@
+using Microsoft.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.Modeling;
+
+namespace LINGYUN.Abp.EntityFrameworkCore;
+public class EfCoreTestDbContext : AbpDbContext
+{
+ public virtual DbSet TestEntities { get; set; }
+
+ public EfCoreTestDbContext(
+ DbContextOptions options) : base(options)
+ {
+ }
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ base.OnModelCreating(modelBuilder);
+
+ modelBuilder.Entity(b =>
+ {
+ b.ConfigureByConvention();
+ });
+ }
+}
diff --git a/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/EfCoreTestEntity.cs b/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/EfCoreTestEntity.cs
new file mode 100644
index 000000000..85d086077
--- /dev/null
+++ b/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/EfCoreTestEntity.cs
@@ -0,0 +1,25 @@
+using System;
+using Volo.Abp.Domain.Entities;
+
+namespace LINGYUN.Abp.EntityFrameworkCore;
+
+public class EfCoreTestEntity : Entity
+{
+ public virtual string PropString { get; set; }
+ public virtual int? PropInt32 { get; set; }
+ public virtual long? PropInt64 { get; set; }
+ public virtual DateTime? DateTime { get; set; }
+ public EfCoreTestEntity(
+ Guid id,
+ string propString = null,
+ int? propInt32 = null,
+ long? propInt64 = null,
+ DateTime? dateTime = null)
+ : base(id)
+ {
+ PropString = propString;
+ PropInt32 = propInt32;
+ PropInt64 = propInt64;
+ DateTime = dateTime;
+ }
+}
diff --git a/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/EfCoreTestEntityDataSeeder.cs b/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/EfCoreTestEntityDataSeeder.cs
new file mode 100644
index 000000000..879a59c3e
--- /dev/null
+++ b/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN/Abp/EntityFrameworkCore/EfCoreTestEntityDataSeeder.cs
@@ -0,0 +1,33 @@
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Storage;
+using System;
+using System.Threading.Tasks;
+
+namespace LINGYUN.Abp.EntityFrameworkCore;
+public class EfCoreTestEntityDataSeeder
+{
+ private readonly EfCoreTestDbContext _dbContext;
+
+ public EfCoreTestEntityDataSeeder(
+ EfCoreTestDbContext dbContext)
+ {
+ _dbContext = dbContext;
+ }
+
+ public async virtual Task SeedAsync()
+ {
+ //_dbContext.GetService().CreateTables();
+
+ await _dbContext.TestEntities.AddAsync(
+ new EfCoreTestEntity(Guid.NewGuid(), "1223", 1024, 1024L, new DateTime(2021, 10, 1, 0, 0, 0)));
+
+ await _dbContext.TestEntities.AddAsync(
+ new EfCoreTestEntity(Guid.NewGuid(), null, 2048, 2048L, new DateTime(2022, 10, 1, 12, 0, 0)));
+
+ await _dbContext.TestEntities.AddAsync(
+ new EfCoreTestEntity(Guid.NewGuid(), "3221", null, 4096L, null));
+
+ await _dbContext.TestEntities.AddAsync(
+ new EfCoreTestEntity(Guid.NewGuid(), null, null, null, new DateTime(2022, 1, 1, 12, 0, 0)));
+ }
+}
diff --git a/aspnet-core/tests/LINGYUN.Linq.Dynamic.Queryable.Tests/LINGYUN.Linq.Dynamic.Queryable.Tests.csproj b/aspnet-core/tests/LINGYUN.Linq.Dynamic.Queryable.Tests/LINGYUN.Linq.Dynamic.Queryable.Tests.csproj
new file mode 100644
index 000000000..06a5a5e68
--- /dev/null
+++ b/aspnet-core/tests/LINGYUN.Linq.Dynamic.Queryable.Tests/LINGYUN.Linq.Dynamic.Queryable.Tests.csproj
@@ -0,0 +1,18 @@
+
+
+
+ net6.0
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/tests/LINGYUN.Linq.Dynamic.Queryable.Tests/LINGYUN/Linq/Dynamic/Queryable/DynamicQueryableTestBase.cs b/aspnet-core/tests/LINGYUN.Linq.Dynamic.Queryable.Tests/LINGYUN/Linq/Dynamic/Queryable/DynamicQueryableTestBase.cs
new file mode 100644
index 000000000..ce3deeb06
--- /dev/null
+++ b/aspnet-core/tests/LINGYUN.Linq.Dynamic.Queryable.Tests/LINGYUN/Linq/Dynamic/Queryable/DynamicQueryableTestBase.cs
@@ -0,0 +1,5 @@
+namespace LINGYUN.Linq.Dynamic.Queryable;
+
+public abstract class DynamicQueryableTestBase : AbpTestsBase
+{
+}
diff --git a/aspnet-core/tests/LINGYUN.Linq.Dynamic.Queryable.Tests/LINGYUN/Linq/Dynamic/Queryable/DynamicQueryableTestModule.cs b/aspnet-core/tests/LINGYUN.Linq.Dynamic.Queryable.Tests/LINGYUN/Linq/Dynamic/Queryable/DynamicQueryableTestModule.cs
new file mode 100644
index 000000000..d9949255f
--- /dev/null
+++ b/aspnet-core/tests/LINGYUN.Linq.Dynamic.Queryable.Tests/LINGYUN/Linq/Dynamic/Queryable/DynamicQueryableTestModule.cs
@@ -0,0 +1,8 @@
+using Volo.Abp.Modularity;
+
+namespace LINGYUN.Linq.Dynamic.Queryable;
+
+[DependsOn(typeof(AbpTestsBaseModule))]
+public class DynamicQueryableTestModule : AbpModule
+{
+}
diff --git a/aspnet-core/tests/LINGYUN.Linq.Dynamic.Queryable.Tests/LINGYUN/Linq/Dynamic/Queryable/DynamicQueryableTests.cs b/aspnet-core/tests/LINGYUN.Linq.Dynamic.Queryable.Tests/LINGYUN/Linq/Dynamic/Queryable/DynamicQueryableTests.cs
new file mode 100644
index 000000000..b106f7313
--- /dev/null
+++ b/aspnet-core/tests/LINGYUN.Linq.Dynamic.Queryable.Tests/LINGYUN/Linq/Dynamic/Queryable/DynamicQueryableTests.cs
@@ -0,0 +1,337 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LINGYUN.Linq.Dynamic.Queryable;
+
+public class LinqTestClass
+{
+ public string StringNull { get; set; }
+ public string StringRequired { get; set; }
+ public long? Int64Null { get; set; }
+ public long Int64Required { get; set; }
+ public DateTime? DateTimeNull { get; set; }
+ public DateTime DateTimeRequired { get; set; }
+ public DateOnly? DateOnlyNull { get; set; }
+ public DateOnly DateOnlyRequired { get; set; }
+ public TimeOnly? TimeOnlyNull { get; set; }
+ public TimeOnly TimeOnlyRequired { get; set; }
+}
+
+public class DynamicQueryableTests : DynamicQueryableTestBase
+{
+ private readonly static List _testClasses;
+ static DynamicQueryableTests()
+ {
+ _testClasses = new List
+ {
+ new LinqTestClass
+ {
+ StringNull = null,
+ StringRequired = "3211",
+ DateOnlyNull = new DateOnly(2022, 1, 1),
+ DateOnlyRequired = new DateOnly(2022, 10, 1),
+ TimeOnlyNull = null,
+ TimeOnlyRequired = new TimeOnly(12, 0, 0),
+ DateTimeNull = new DateTime(2021, 1, 1, 0, 0, 0),
+ DateTimeRequired = new DateTime(2022, 10, 1, 12, 0, 0),
+ Int64Null = null,
+ Int64Required = 1024L
+ },
+ new LinqTestClass
+ {
+ StringNull = "not null",
+ StringRequired = "1123",
+ DateOnlyNull = null,
+ DateOnlyRequired = new DateOnly(2021, 10, 1),
+ TimeOnlyNull = new TimeOnly(0, 0, 0),
+ TimeOnlyRequired = new TimeOnly(1, 0, 0),
+ DateTimeNull = null,
+ DateTimeRequired = new DateTime(2021, 1, 1, 0, 0, 0),
+ Int64Null = null,
+ Int64Required = 2048L
+ },
+ };
+ }
+
+ [Fact]
+ public void Should_Null()
+ {
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new DynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.Null,
+ Field = nameof(LinqTestClass.Int64Null),
+ Logic = DynamicLogic.And
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = _testClasses.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(2);
+ }
+
+ [Fact]
+ public void Should_Not_Null()
+ {
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new DynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.NotNull,
+ Field = nameof(LinqTestClass.StringNull),
+ Logic = DynamicLogic.And
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = _testClasses.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(1);
+ }
+
+ [Fact]
+ public void Should_Equal()
+ {
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new DynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.Equal,
+ Field = nameof(LinqTestClass.StringRequired),
+ Logic = DynamicLogic.And,
+ Value = "1123"
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = _testClasses.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(1);
+ }
+
+ [Fact]
+ public void Should_Not_Equal()
+ {
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new DynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.NotEqual,
+ Field = nameof(LinqTestClass.StringRequired),
+ Logic = DynamicLogic.And,
+ Value = "1123"
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = _testClasses.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(1);
+ }
+
+ [Fact]
+ public void Should_Less_Than()
+ {
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new DynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.LessThan,
+ Field = nameof(LinqTestClass.Int64Required),
+ Logic = DynamicLogic.And,
+ Value = 2048L
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = _testClasses.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(1);
+ }
+
+ [Fact]
+ public void Should_Less_Than_Or_Equal()
+ {
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new DynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.LessThanOrEqual,
+ Field = nameof(LinqTestClass.Int64Required),
+ Logic = DynamicLogic.And,
+ Value = 2048L
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = _testClasses.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(2);
+ }
+
+ [Fact]
+ public void Should_Greater_Than()
+ {
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new DynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.GreaterThan,
+ Field = nameof(LinqTestClass.Int64Null),
+ Logic = DynamicLogic.And,
+ Value = 1024L
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = _testClasses.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(0);
+ }
+
+ [Fact]
+ public void Should_Greater_Than_Or_Equal()
+ {
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new DynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.GreaterThanOrEqual,
+ Field = nameof(LinqTestClass.Int64Required),
+ Logic = DynamicLogic.And,
+ Value = 1024L
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = _testClasses.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(2);
+ }
+
+ [Fact]
+ public void Should_Starts_With()
+ {
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new DynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.StartsWith,
+ Field = nameof(LinqTestClass.StringNull),
+ Logic = DynamicLogic.And,
+ Value = "not"
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = _testClasses.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(1);
+ }
+
+ [Fact]
+ public void Should_Not_Starts_With()
+ {
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new DynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.NotStartsWith,
+ Field = nameof(LinqTestClass.StringNull),
+ Logic = DynamicLogic.And,
+ Value = "not"
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = _testClasses.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(1);
+ }
+
+ [Fact]
+ public void Should_Ends_With()
+ {
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new DynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.EndsWith,
+ Field = nameof(LinqTestClass.StringNull),
+ Logic = DynamicLogic.And,
+ Value = "null"
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = _testClasses.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(1);
+ }
+
+ [Fact]
+ public void Should_Not_Ends_With()
+ {
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new DynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.NotEndsWith,
+ Field = nameof(LinqTestClass.StringNull),
+ Logic = DynamicLogic.And,
+ Value = "null"
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = _testClasses.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(1);
+ }
+
+ [Fact]
+ public void Should_Contains()
+ {
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new DynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.Contains,
+ Field = nameof(LinqTestClass.StringNull),
+ Logic = DynamicLogic.And,
+ Value = "null"
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = _testClasses.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(1);
+ }
+
+ [Fact]
+ public void Should_Not_Contains()
+ {
+ Expression> exp = (_) => true;
+
+ var dynamicQueryable = new DynamicQueryable();
+ dynamicQueryable.Paramters.Add(new DynamicParamter
+ {
+ Comparison = DynamicComparison.NotContains,
+ Field = nameof(LinqTestClass.StringNull),
+ Logic = DynamicLogic.And,
+ Value = "test"
+ });
+
+ exp = exp.DynamicQuery(dynamicQueryable);
+
+ var result = _testClasses.Where(exp.Compile()).ToList();
+ result.Count.ShouldBe(2);
+ }
+}
diff --git a/aspnet-core/tests/LINGYUN.Linq.Dynamic.Queryable.Tests/Usings.cs b/aspnet-core/tests/LINGYUN.Linq.Dynamic.Queryable.Tests/Usings.cs
new file mode 100644
index 000000000..5a47b21df
--- /dev/null
+++ b/aspnet-core/tests/LINGYUN.Linq.Dynamic.Queryable.Tests/Usings.cs
@@ -0,0 +1,4 @@
+global using Xunit;
+global using Shouldly;
+global using LINGYUN.Abp.Tests;
+global using LINGYUN.Linq.Dynamic.Queryable;