diff --git a/CodeSmith/CSharp/ApiGenerate.cst b/CodeSmith/CSharp/ApiGenerate.cst
new file mode 100644
index 0000000000000000000000000000000000000000..9d201f29cef79c89e77c818dadfe5f92f9a0c1f4
--- /dev/null
+++ b/CodeSmith/CSharp/ApiGenerate.cst
@@ -0,0 +1,226 @@
+<%--
+Author: yubaolee
+Description: 用于生成OpenAuth.WebApi接口相关代码,包括controller/app/实体/dbcontext
+--%>
+<%@ Template Language="C#" TargetLanguage="Text" Debug="True" OutputType="Normal" %>
+
+<%@ Assembly Name="SchemaExplorer" %>
+<%@ Assembly Name="CodeSmith.CustomProperties" %>
+
+<%@ Assembly Name="Mono.Cecil" Path="..\Common" %>
+<%@ Assembly Name="ICSharpCode.NRefactory" Path="..\Common" %>
+<%@ Assembly Name="ICSharpCode.NRefactory.CSharp" Path="..\Common" %>
+
+<%@ Assembly Src="Internal\Model.cs" %>
+<%@ Assembly Src="Internal\Extensions.cs" %>
+<%@ Assembly Src="Internal\Generator.cs" %>
+<%@ Assembly Src="Internal\Parser.cs" %>
+
+<%@ Import Namespace="System.Collections.Generic" %>
+<%@ Import Namespace="System.IO" %>
+<%@ Import Namespace="System.Linq" %>
+<%@ Import Namespace="System.Text" %>
+<%@ Import Namespace="System.Text.RegularExpressions" %>
+<%@ Import Namespace="System.Diagnostics" %>
+
+<%@ Import Namespace="SchemaMapper" %>
+
+<%@ Property Name="WholeDb"
+Type="System.Boolean"
+Category="1.Database"
+Default="true"
+Description="是否直接生成选定数据库中的所有表" %>
+
+<%@ Property Name="HeaderModel"
+Type="System.Boolean"
+Category="1.Database"
+Default="true"
+Description="是否为启用头表模式,即类似‘入库订单’界面" %>
+
+<%@ Property Name="SourceDatabase"
+ Type="SchemaExplorer.DatabaseSchema"
+ Category="1.Database"
+ Description="The source database." %>
+
+<%@ Property Name="SourceTables"
+Type="SchemaExplorer.TableSchemaCollection"
+Category="1.Database" Description="可以选择一个或多个表(使用Ctrl键)" %>
+
+<%@ Property Name="directory"
+ Type="System.String"
+ Default=".\"
+ Optional="True"
+ Description="代码生成路径"
+ Editor="System.Windows.Forms.Design.FolderNameEditor, System.Design, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" %>
+
+<%@ Property Name="ContextNamespace"
+ Type="System.String"
+ Category="2.Class"
+ Default="OpenAuth.Repository"
+ OnChanged="OnContextNamespaceChanged"
+ Description="DbContext默认命名空间,尽量不要更改"%>
+<%@ Property Name="EntityNamespace"
+ Type="System.String"
+ Default="OpenAuth.Repository.Domain"
+ Category="2.Class"
+ Description="实体默认命名空间,尽量不要更改"%>
+
+
+<%@ Register Name="EntityGeneratedClass"
+ Template="Internal\Entity.Generated.cst"
+ MergeProperties="False" %>
+
+<%@ Register Name="ContextGeneratedClass"
+ Template="Internal\Context.Generated.cst"
+ MergeProperties="True" %>
+
+<%@ Register Name="ApplicationGenerateClass"
+ Template="ApiGenerate\Application.cst"
+ MergeProperties="False" %>
+<%@ Register Name="RequestGenerateClass"
+ Template="ApiGenerate\Request.cst"
+ MergeProperties="False" %>
+<%@ Register Name="ModifyReqGenerateClass"
+ Template="ApiGenerate\ModifyReq.cst"
+ MergeProperties="False" %>
+<%@ Register Name="ControllerGenerateClass"
+ Template="ApiGenerate\Controller.cst"
+ MergeProperties="False" %>
+
+开始创建OpenAuth.Core WebApi相关代码 ...
+<% Generate(); %>
+
+
\ No newline at end of file
diff --git a/CodeSmith/CSharp/ApiGenerate/Application.cst b/CodeSmith/CSharp/ApiGenerate/Application.cst
new file mode 100644
index 0000000000000000000000000000000000000000..28689ccbd24029ff011a31e8d34606ebf51fd02c
--- /dev/null
+++ b/CodeSmith/CSharp/ApiGenerate/Application.cst
@@ -0,0 +1,185 @@
+<%--
+Name: Database Table Properties
+Author: yubaolee
+Description: Create a list of properties from a database table
+--%>
+<%@ CodeTemplate Language="C#" Encoding="utf-8" TargetLanguage="C#" Debug="True" Description="应用层" %>
+<%@ Map Name="CSharpAlias" Src="System-CSharpAlias" Description="System to C# Type Map" %>
+<%@ Assembly Name="SchemaExplorer" %>
+<%@ Import Namespace="SchemaExplorer" %>
+<%@ Property Name="Table"
+ Type="SchemaExplorer.TableSchema" %>
+
+<%@ Property Name="HeaderModel"
+Type="System.Boolean"
+Category="1.Database"
+Default="true"
+Description="是否为启用头表模式,即类似‘入库订单’界面" %>
+
+using System;
+using System.Linq;
+using Infrastructure;
+using OpenAuth.App.Interface;
+using OpenAuth.App.Request;
+using OpenAuth.App.Response;
+using OpenAuth.Repository.Domain;
+using OpenAuth.Repository.Interface;
+
+
+namespace OpenAuth.App
+{
+ public class <%=Table.Name%>App : BaseApp<<%=Table.Name%>>
+ {
+ private RevelanceManagerApp _revelanceApp;
+
+ ///
+ /// 加载列表
+ ///
+ public TableData Load(Query<%=Table.Name%>ListReq request)
+ {
+ var loginContext = _auth.GetCurrentUser();
+ if (loginContext == null)
+ {
+ throw new CommonException("登录已过期", Define.INVALID_TOKEN);
+ }
+
+ var properties = loginContext.GetProperties("<%=Table.Name%>");
+
+ if (properties == null || properties.Count == 0)
+ {
+ throw new Exception("当前登录用户没有访问该模块字段的权限,请联系管理员配置");
+ }
+
+
+ var result = new TableData();
+ var objs = UnitWork.Find<<%=Table.Name%>>(null);
+ if (!string.IsNullOrEmpty(request.key))
+ {
+ objs = objs.Where(u => u.Id.Contains(request.key));
+ }
+
+
+ var propertyStr = string.Join(',', properties.Select(u => u.Key));
+ result.columnHeaders = properties;
+ result.data = objs.OrderBy(u => u.Id)
+ .Skip((request.page - 1) * request.limit)
+ .Take(request.limit).Select($"new ({propertyStr})");
+ result.count = objs.Count();
+ return result;
+ }
+
+ <%
+ if(Table.Name.Contains("Tbl") && (!Table.Name.Contains("Dtbl")) && this.HeaderModel){
+ var dtblName = Table.Name.Replace("Tbl","Dtbl"); //明细表的表名
+ %>
+
+ public void Add(AddOrUpdate<%=Table.Name%>Req req)
+ {
+ var obj = req.MapTo<<%=Table.Name%>>();
+ //todo:补充或调整自己需要的字段
+ obj.CreateTime = DateTime.Now;
+ var user = _auth.GetCurrentUser().User;
+ obj.CreateUserId = user.Id;
+ obj.CreateUserName = user.Name;
+ UnitWork.Add(obj);
+ if (req.<%=dtblName%>Reqs != null && req.<%=dtblName%>Reqs.Any())
+ {
+ foreach (var detail in req.<%=dtblName%>Reqs)
+ {
+ detail.ForeignKeyId = obj.Id; //todo:调整自己的明细表外键
+ _<%=dtblName%>App.AddNoSave(detail);
+ }
+ }
+
+ UnitWork.Save();
+ }
+
+ public void Update(AddOrUpdate<%=Table.Name%>Req obj)
+ {
+ var user = _auth.GetCurrentUser().User;
+
+ if (obj.<%=dtblName%>Reqs != null && obj.<%=dtblName%>Reqs.Any())
+ {
+ //id为空的添加
+ foreach (var detail in obj.<%=dtblName%>Reqs.Where(u =>string.IsNullOrEmpty(u.Id)))
+ {
+ detail.ForeignKeyId = obj.Id; //todo:调整自己的明细表外键
+ _<%=dtblName%>App.AddNoSave(detail);
+ }
+
+ //id比数据库少的,删除
+ var containids = obj.<%=dtblName%>Reqs.Select(u => u.Id)
+ .Where(u =>!string.IsNullOrEmpty(u)).ToList();
+ if (containids.Any())
+ {
+ UnitWork.Delete<<%=dtblName%>>(u =>(!containids.Contains(u.Id)) && u.ForeignKeyId == obj.Id); //todo:调整自己的明细表外键
+ }
+
+
+ //更新id相同的
+ foreach (var detail in obj.<%=dtblName%>Reqs.Where(u =>!string.IsNullOrEmpty(u.Id)))
+ {
+ _<%=dtblName%>App.Update(detail);
+ }
+ }
+
+ UnitWork.Update<<%=Table.Name%>>(u => u.Id == obj.Id, u => new <%=Table.Name%>
+ {
+ <% foreach(ColumnSchema p in Table.Columns) {
+ if(p.IsPrimaryKeyMember) continue;
+ %>
+ <%= p.Name%> = obj.<%= p.Name%>,
+ <% } %>
+ UpdateTime = DateTime.Now,
+ UpdateUserId = user.Id,
+ UpdateUserName = user.Name
+ //todo:补充或调整自己需要的字段
+ });
+
+ UnitWork.Save();
+
+ }
+
+
+ <%
+ }else{ %>
+ public void Add(AddOrUpdate<%=Table.Name%>Req req)
+ {
+ var obj = req.MapTo<<%=Table.Name%>>();
+ //todo:补充或调整自己需要的字段
+ obj.CreateTime = DateTime.Now;
+ var user = _auth.GetCurrentUser().User;
+ obj.CreateUserId = user.Id;
+ obj.CreateUserName = user.Name;
+ Repository.Add(obj);
+ }
+
+ public void Update(AddOrUpdate<%=Table.Name%>Req obj)
+ {
+ var user = _auth.GetCurrentUser().User;
+ UnitWork.Update<<%=Table.Name%>>(u => u.Id == obj.Id, u => new <%=Table.Name%>
+ {
+ <% foreach(ColumnSchema p in Table.Columns) {
+ if(p.IsPrimaryKeyMember) continue;
+ %>
+ <%= p.Name%> = obj.<%= p.Name%>,
+ <% } %>
+ UpdateTime = DateTime.Now,
+ UpdateUserId = user.Id,
+ UpdateUserName = user.Name
+ //todo:补充或调整自己需要的字段
+ });
+
+ }
+
+ <%
+ }
+ %>
+
+ public <%=Table.Name%>App(IUnitWork unitWork, IRepository<<%=Table.Name%>> repository,
+ RevelanceManagerApp app, IAuth auth) : base(unitWork, repository,auth)
+ {
+ _revelanceApp = app;
+ }
+ }
+}
\ No newline at end of file
diff --git a/CodeSmith/CSharp/ApiGenerate/Controller.cst b/CodeSmith/CSharp/ApiGenerate/Controller.cst
new file mode 100644
index 0000000000000000000000000000000000000000..fdfb966f1f76b0e50c580350e7951bdc5c26a3dd
--- /dev/null
+++ b/CodeSmith/CSharp/ApiGenerate/Controller.cst
@@ -0,0 +1,122 @@
+<%--
+Name: Database Table Properties
+Author: yubaolee
+Description: Create a list of properties from a database table
+--%>
+<%@ CodeTemplate Language="C#" Encoding="utf-8" TargetLanguage="C#" Debug="True" Description="控制器" %>
+<%@ Property Name="ModuleName" Type="String" Category="Context" Description="模块名称" %>
+<%@ Map Name="CSharpAlias" Src="System-CSharpAlias" Description="System to C# Type Map" %>
+<%@ Assembly Name="SchemaExplorer" %>
+<%@ Import Namespace="SchemaExplorer" %>
+
+using System;
+using Infrastructure;
+using Microsoft.AspNetCore.Mvc;
+using OpenAuth.App;
+using OpenAuth.App.Request;
+using OpenAuth.App.Response;
+using OpenAuth.Repository.Domain;
+
+namespace OpenAuth.WebApi.Controllers
+{
+ ///
+ /// <%=ModuleName%>操作
+ ///
+ [Route("api/[controller]/[action]")]
+ [ApiController]
+ public class <%=ModuleName%>sController : ControllerBase
+ {
+ private readonly <%=ModuleName%>App _app;
+
+ //获取详情
+ [HttpGet]
+ public Response<<%=ModuleName%>> Get(string id)
+ {
+ var result = new Response<<%=ModuleName%>>();
+ try
+ {
+ result.Result = _app.Get(id);
+ }
+ catch (Exception ex)
+ {
+ result.Code = 500;
+ result.Message = ex.InnerException?.Message ?? ex.Message;
+ }
+
+ return result;
+ }
+
+ //添加
+ [HttpPost]
+ public Response Add(AddOrUpdate<%=ModuleName%>Req obj)
+ {
+ var result = new Response();
+ try
+ {
+ _app.Add(obj);
+
+ }
+ catch (Exception ex)
+ {
+ result.Code = 500;
+ result.Message = ex.InnerException?.Message ?? ex.Message;
+ }
+
+ return result;
+ }
+
+ //修改
+ [HttpPost]
+ public Response Update(AddOrUpdate<%=ModuleName%>Req obj)
+ {
+ var result = new Response();
+ try
+ {
+ _app.Update(obj);
+
+ }
+ catch (Exception ex)
+ {
+ result.Code = 500;
+ result.Message = ex.InnerException?.Message ?? ex.Message;
+ }
+
+ return result;
+ }
+
+ ///
+ /// 加载列表
+ ///
+ [HttpGet]
+ public TableData Load([FromQuery]Query<%=ModuleName%>ListReq request)
+ {
+ return _app.Load(request);
+ }
+
+ ///
+ /// 批量删除
+ ///
+ [HttpPost]
+ public Response Delete([FromBody]string[] ids)
+ {
+ var result = new Response();
+ try
+ {
+ _app.Delete(ids);
+
+ }
+ catch (Exception ex)
+ {
+ result.Code = 500;
+ result.Message = ex.InnerException?.Message ?? ex.Message;
+ }
+
+ return result;
+ }
+
+ public <%=ModuleName%>sController(<%=ModuleName%>App app)
+ {
+ _app = app;
+ }
+ }
+}
diff --git a/CodeSmith/CSharp/ApiGenerate/ModifyReq.cst b/CodeSmith/CSharp/ApiGenerate/ModifyReq.cst
new file mode 100644
index 0000000000000000000000000000000000000000..867bfd0cd3c42d07c06b7fb29e737c3fbd267482
--- /dev/null
+++ b/CodeSmith/CSharp/ApiGenerate/ModifyReq.cst
@@ -0,0 +1,66 @@
+<%@ Template Language="C#" TargetLanguage="C#" Debug="True" Encoding="UTF-8" %>
+
+<%@ Assembly Src="../Internal/Model.cs" %>
+<%@ Assembly Src="../Internal/Extensions.cs" %>
+
+<%@ Import Namespace="System.Collections.Generic" %>
+<%@ Import Namespace="System.Linq" %>
+<%@ Import Namespace="System.Text" %>
+<%@ Import Namespace="System.Text.RegularExpressions" %>
+
+<%@ Import Namespace="SchemaMapper" %>
+
+<%@ Property Name="Table"
+ Type="SchemaExplorer.TableSchema" %>
+
+<%@ Property Name="HeaderModel"
+Type="System.Boolean"
+Category="1.Database"
+Default="true"
+Description="是否为启用头表模式,即类似‘入库订单’界面" %>
+
+<%@ Property Name="EntityNamespace"
+ Type="System.String" %>
+//------------------------------------------------------------------------------
+//
+// This code was generated by a CodeSmith Template.
+//
+// DO NOT MODIFY contents of this file. Changes to this
+// file will be lost if the code is regenerated.
+// Author:Yubao Li
+//
+//------------------------------------------------------------------------------
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Text;
+using OpenAuth.Repository.Core;
+
+namespace OpenAuth.App.Request
+{
+ ///
+ /// <%= Table.Description %>
+ ///
+ [Table("<%= Table.Name%>")]
+ public partial class AddOrUpdate<%= Table.Name %>Req
+ {
+
+ <% foreach(ColumnSchema p in Table.Columns) {
+
+ %>
+ ///
+ /// <%=p.Description %>
+ ///
+ public <%= p.SystemType.ToNullableType(p.AllowDBNull == true) %> <%= p.Name%> { get; set; }
+ <% } %>
+
+ //todo:添加自己的请求字段
+ <%
+ if(Table.Name.Contains("Tbl") && (!Table.Name.Contains("Dtbl")) && this.HeaderModel){
+ var dtblName = Table.Name.Replace("Tbl","Dtbl"); //明细表的表名
+ %>
+ public ListReq> <%=dtblName%>Reqs { get; set; }
+ <% } %>
+ }
+}
\ No newline at end of file
diff --git a/CodeSmith/CSharp/Web/Request.cst b/CodeSmith/CSharp/ApiGenerate/Request.cst
similarity index 93%
rename from CodeSmith/CSharp/Web/Request.cst
rename to CodeSmith/CSharp/ApiGenerate/Request.cst
index 734ad9ad6585c35b2fc8795920237c4225cc04e5..c7b9cf2f20d9218bdf9965f25f2b7d6cc355540d 100644
--- a/CodeSmith/CSharp/Web/Request.cst
+++ b/CodeSmith/CSharp/ApiGenerate/Request.cst
@@ -12,6 +12,6 @@ namespace OpenAuth.App.Request
{
public class Query<%=ModuleName%>ListReq : PageReq
{
- public string orgId { get; set; }
+ //todo:添加自己的请求字段
}
}
\ No newline at end of file
diff --git a/CodeSmith/CSharp/Entity.cst b/CodeSmith/CSharp/Entity.cst
deleted file mode 100644
index 90952b98f534b1617177f02436aa3772585ab47a..0000000000000000000000000000000000000000
--- a/CodeSmith/CSharp/Entity.cst
+++ /dev/null
@@ -1,309 +0,0 @@
-<%@ Template Language="C#" TargetLanguage="Text" Debug="True" OutputType="None" %>
-
-<%@ Assembly Name="SchemaExplorer" %>
-<%@ Assembly Name="CodeSmith.CustomProperties" %>
-
-<%@ Assembly Name="Mono.Cecil" Path="..\Common" %>
-<%@ Assembly Name="ICSharpCode.NRefactory" Path="..\Common" %>
-<%@ Assembly Name="ICSharpCode.NRefactory.CSharp" Path="..\Common" %>
-
-<%@ Assembly Src="Internal\Model.cs" %>
-<%@ Assembly Src="Internal\Extensions.cs" %>
-<%@ Assembly Src="Internal\Generator.cs" %>
-<%@ Assembly Src="Internal\Parser.cs" %>
-
-<%@ Import Namespace="System.Collections.Generic" %>
-<%@ Import Namespace="System.IO" %>
-<%@ Import Namespace="System.Linq" %>
-<%@ Import Namespace="System.Text" %>
-<%@ Import Namespace="System.Text.RegularExpressions" %>
-
-<%@ Import Namespace="SchemaMapper" %>
-
-<%@ Property Name="SourceDatabase"
- Type="SchemaExplorer.DatabaseSchema"
- Category="1.Database"
- OnChanged="OnSourceDatabaseChanged"
- Description="The source database." %>
-
-<%@ Property Name="ContextNamespace"
- Type="System.String"
- Category="2.Class"
- OnChanged="OnContextNamespaceChanged"
- Description="The namespace to use for the data context class files."%>
-<%@ Property Name="EntityNamespace"
- Type="System.String"
- Category="2.Class"
- Description="The namespace to use for the entity class files."%>
-<%@ Property Name="MappingNamespace"
- Type="System.String"
- Category="2.Class"
- Description="The namespace to use for the mapping class files."%>
-
-<%@ Property Name="ContextDirectory"
- Category="3.Output"
- Type="System.String"
- Default=".\"
- Optional="True"
- Description="The folder to save the generated context files."
- Editor="System.Windows.Forms.Design.FolderNameEditor, System.Design, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" %>
-<%@ Property Name="EntityDirectory"
- Category="3.Output"
- Type="System.String"
- Default=".\Entities"
- Optional="True"
- Description="The folder to save the generated entity files."
- Editor="System.Windows.Forms.Design.FolderNameEditor, System.Design, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" %>
-<%@ Property Name="MappingDirectory"
- Category="3.Output"
- Type="System.String"
- Default=".\Mapping"
- Optional="True"
- Description="The folder to save the generated mapping files."
- Editor="System.Windows.Forms.Design.FolderNameEditor, System.Design, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" %>
-
-<%@ Property Name="TableNaming"
- Type="SchemaMapper.TableNaming"
- Category="4.Hints"
- Default="Singular"
- Description="Provide generator a hint as to how the tables are named." %>
-<%@ Property Name="EntityNaming"
- Type="SchemaMapper.EntityNaming"
- Category="4.Hints"
- Default="Singular"
- Description="Tell generator how the entities are to be named." %>
-<%@ Property Name="RelationshipNaming"
- Type="SchemaMapper.RelationshipNaming"
- Category="4.Hints"
- Default="Plural"
- Description="Tell generator how the relationships are to be named." %>
-<%@ Property Name="ContextNaming"
- Type="SchemaMapper.ContextNaming"
- Category="4.Hints"
- Default="Plural"
- Description="Tell generator how the context properties are to be named." %>
-
-<%@ Property Name="IgnoreList"
- Type="CodeSmith.CustomProperties.StringCollection"
- Category="5.Customization"
- Default="sysdiagrams$"
- Optional="True"
- Description="List of regular expressions to ignore tables, views and commands when generating mapping." %>
-<%@ Property Name="InclusionMode"
- Type="Boolean"
- Category="5.Customization"
- Default="False"
- Optional="True"
- Description="Change the IgnoreList to be a list of table to include instead of ignore." %>
-<%@ Property Name="CleanExpressions"
- Type="CodeSmith.CustomProperties.StringCollection"
- Category="5.Customization"
- Default="^(sp|tbl|udf|vw)_"
- Optional="True"
- Description="List of regular expressions to clean table, view and column names." %>
-<%@ Property Name="InterfaceMode"
- Type="Boolean"
- Category="5.Customization"
- Default="False"
- Optional="True"
- Description="Use interfaces for DbContext." %>
-
-
-
-<%@ Register Name="ContextGeneratedClass"
- Template="Internal\Context.Generated.cst"
- MergeProperties="False" %>
-
-<%@ Register Name="EntityGeneratedClass"
- Template="Internal\Entity.Generated.cst"
- MergeProperties="False" %>
-
-<%@ Register Name="MappingGeneratedClass"
- Template="Internal\Mapping.Generated.cst"
- MergeProperties="False" %>
-
-Generating Entities ...
-<% Generate(); %>
-
-
\ No newline at end of file
diff --git a/CodeSmith/CSharp/Internal/Context.Generated.cst b/CodeSmith/CSharp/Internal/Context.Generated.cst
index a314e2faf3be47b106442eb3c623fd57e3b2f53a..1a61f6e39cc0e13a11551d911e2a718f03fd58a2 100644
--- a/CodeSmith/CSharp/Internal/Context.Generated.cst
+++ b/CodeSmith/CSharp/Internal/Context.Generated.cst
@@ -1,7 +1,7 @@
<%@ Template Language="C#" TargetLanguage="C#" Debug="True" Encoding="UTF-8" %>
-<%@ Assembly Src="Model.cs" %>
-<%@ Assembly Src="Extensions.cs" %>
+<%@ Assembly Src="../Internal/Model.cs" %>
+<%@ Assembly Src="../Internal/Extensions.cs" %>
<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.Linq" %>
@@ -10,87 +10,72 @@
<%@ Import Namespace="SchemaMapper" %>
-<%@ Property Name="EntityContext" Type="SchemaMapper.EntityContext" %>
+<%@ Property Name="WholeDb"
+Type="System.Boolean"
+Category="1.Database"
+Default="true"
+Description="是否为整个数据库" %>
+
+<%@ Property Name="SourceDatabase"
+ Type="SchemaExplorer.DatabaseSchema"
+ Category="1.Database"
+ Description="The source database." %>
+
+<%@ Property Name="SourceTables"
+Type="SchemaExplorer.TableSchemaCollection"
+Category="1.Database" Description="选择部分表" %>
<%@ Property Name="ContextNamespace" Type="System.String" %>
<%@ Property Name="EntityNamespace" Type="System.String" %>
-<%@ Property Name="MappingNamespace" Type="System.String" %>
-<%@ Property Name="InterfaceMode" Type="Boolean" Default="False" Optional="True" %>
+
-//------------------------------------------------------------------------------
-//
-// This code was generated by a CodeSmith Template.
-//
-// DO NOT MODIFY contents of this file. Changes to this
-// file will be lost if the code is regenerated.
-//
-//------------------------------------------------------------------------------
-using System;
-using System.Data.Entity;
-using System.Collections.Generic;
+using Microsoft.EntityFrameworkCore;
using <%= EntityNamespace %>;
-using <%= MappingNamespace %>;
namespace <%= ContextNamespace %>
{
-<% if (InterfaceMode) { %>
- public interface IDbContext : IDisposable
- {
- System.Data.Entity.Database Database { get; }
- System.Data.Entity.Infrastructure.DbChangeTracker ChangeTracker { get; }
- System.Data.Entity.Infrastructure.DbContextConfiguration Configuration { get; }
-
- System.Data.Entity.Infrastructure.DbEntityEntry Entry(object entity);
- System.Data.Entity.Infrastructure.DbEntityEntry Entry(TEntity entity) where TEntity : class;
-
- IEnumerable GetValidationErrors();
-
- System.Data.Entity.DbSet Set(Type entityType);
- System.Data.Entity.IDbSet Set() where TEntity : class;
-
- int SaveChanges();
- }
-
- public partial interface I<%= EntityContext.ClassName.ToSafeName() %> : IDbContext
- {
-<% foreach(var p in EntityContext.Entities) { %>
- System.Data.Entity.IDbSet<<%= EntityNamespace %>.<%= p.ClassName.ToSafeName() %>> <%= p.ContextName.ToSafeName() %> { get; set; }
-<% } // foreach %>
- }
-
-<% } // if interface %>
- public partial class <%= EntityContext.ClassName.ToSafeName() %>: DbContext<%= InterfaceMode ? ", I" + EntityContext.ClassName.ToSafeName() : string.Empty %>
- {
- static <%= EntityContext.ClassName.ToSafeName() %>()
- {
- Database.SetInitializer< <%= EntityContext.ClassName.ToSafeName() %>>(null);
+ <%
+ string dbContextName;
+ if(WholeDb){
+ dbContextName = SourceDatabase.Name.ToSafeName();
}
- public <%= EntityContext.ClassName.ToSafeName() %>()
- :base("Name=<%= EntityContext.ClassName.ToSafeName() %>")
- { }
-
- public <%= EntityContext.ClassName.ToSafeName() %>(string nameOrConnectionString)
- : base(nameOrConnectionString)
- { }
-
-<% foreach(var p in EntityContext.Entities) { %>
- public System.Data.Entity.<%= InterfaceMode ? "I" : "" %>DbSet<<%= p.ClassName.ToSafeName() %>> <%= p.ContextName.ToSafeName() %> { get; set; }
-<% } // foreach %>
-
- protected override void OnModelCreating(DbModelBuilder modelBuilder)
+ else{
+ dbContextName = SourceTables.First().Database.Name.ToSafeName();
+ }
+ dbContextName = StringUtil.ToPascalCase(dbContextName);
+ Response.WriteLine(" public partial class "+ dbContextName +"Context: DbContext");
+
+ %>
+ {
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
{
-<% foreach(var p in EntityContext.Entities) { %>
- modelBuilder.Configurations.Add(new <%= p.MappingName.ToSafeName() %>());
-<% } // foreach %>
-
- // InitializeMapping(modelBuilder);
+ //当主键为联合主键时,需要把这里的内容拷贝到对应的位置
+ <%
+ TableSchemaCollection tables;
+ if(WholeDb){
+ tables = SourceDatabase.Tables;
+ }
+ else{
+ tables = SourceTables;
+ }
+
+ foreach(TableSchema table in tables)
+ {
+ if(table.PrimaryKeys.Count <=1) continue;
+ var keys = string.Join(",", table.Columns.Where(u=>u.IsPrimaryKeyMember==true)
+ .Select(u =>"c."+u.Name));
+ Response.WriteLine(" modelBuilder.Entity<"+table.Name+">()");
+ Response.WriteLine(" .HasKey(c => new { "+keys+" });");
+ }
+ %>
}
-<% if (InterfaceMode) { %>
- System.Data.Entity.IDbSet IDbContext.Set()
+ <%
+ foreach(TableSchema table in tables)
{
- return base.Set();
+ Response.WriteLine(" public virtual DbSet<"+table.Name+"> "+StringUtil.ToPascalCase(StringUtil.ToPlural(table.Name))+" { get; set; }");
}
-<% } // if interface %>
+ %>
}
}
\ No newline at end of file
diff --git a/CodeSmith/CSharp/Internal/Entity.Generated.cst b/CodeSmith/CSharp/Internal/Entity.Generated.cst
index 632d50d91e29a36be54718dc75025f6c9789428d..ba085a781bf7a984f70bbc06e6eab8b769e84ec6 100644
--- a/CodeSmith/CSharp/Internal/Entity.Generated.cst
+++ b/CodeSmith/CSharp/Internal/Entity.Generated.cst
@@ -1,7 +1,7 @@
<%@ Template Language="C#" TargetLanguage="C#" Debug="True" Encoding="UTF-8" %>
-<%@ Assembly Src="Model.cs" %>
-<%@ Assembly Src="Extensions.cs" %>
+<%@ Assembly Src="../Internal/Model.cs" %>
+<%@ Assembly Src="../Internal/Extensions.cs" %>
<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.Linq" %>
@@ -10,8 +10,8 @@
<%@ Import Namespace="SchemaMapper" %>
-<%@ Property Name="Entity"
- Type="SchemaMapper.Entity" %>
+<%@ Property Name="Table"
+ Type="SchemaExplorer.TableSchema" %>
<%@ Property Name="EntityNamespace"
Type="System.String" %>
@@ -26,47 +26,50 @@
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations.Schema;
using System.Text;
+using OpenAuth.Repository.Core;
namespace <%= EntityNamespace %>
{
///
- /// <%= Entity.Description %>
+ /// <%= Table.Description %>
///
- public partial class <%= Entity.ClassName.ToSafeName() %> : Entity
+ [Table("<%= Table.Name%>")]
+ public partial class <%= Table.Name %> : Entity
{
- public <%= Entity.ClassName.ToSafeName() %>()
+ public <%= Table.Name %>()
{
-<% foreach(var p in Entity.Properties) {
- if(p.IsPrimaryKey ==true) continue;
- string type = p.SystemType.ToNullableType(p.IsNullable == true);
- if(type =="int" || type=="decimal")
- Response.WriteLine(" this."+p.PropertyName.ToSafeName()+"= 0;");
- else if(type =="string")
- Response.WriteLine(" this."+p.PropertyName.ToSafeName()+"= string.Empty;");
- else if(type.ToLower().Contains("datetime"))
- Response.WriteLine(" this."+p.PropertyName.ToSafeName()+"= DateTime.Now;");
- } // foreach %>
-<% foreach(var r in Entity.Relationships.Where(e => e.ThisCardinality == Cardinality.Many)) { %>
- <%= r.ThisPropertyName.ToSafeName() %> = new List<<%= r.OtherEntity.ToSafeName() %>>();
-<% } // foreach %>
+ <% foreach(ColumnSchema p in Table.Columns) {
+ if(p.IsPrimaryKeyMember) continue;
+ string type = p.SystemType.ToNullableType(p.AllowDBNull == true);
+ if(type =="int" || type=="decimal")
+ Response.WriteLine(" this."+p.Name+"= 0;");
+ else if(type =="string")
+ Response.WriteLine(" this."+p.Name+"= string.Empty;");
+ else if(type.ToLower().Contains("datetime"))
+ Response.WriteLine(" this."+p.Name+"= DateTime.Now;");
+ } // foreach %>
}
-<% foreach(var p in Entity.Properties) {
- if(p.IsPrimaryKey ==true) continue;
- %>
+
+ <%
+ foreach(ColumnSchema p in Table.Columns) {
+ if(p.IsPrimaryKeyMember) continue;
+ %>
///
- /// <%=p.Description %>
- ///
- public <%= p.SystemType.ToNullableType(p.IsNullable == true) %> <%= p.PropertyName.ToSafeName() %> { get; set; }
-<% } // foreach %>
-
-<% foreach(var r in Entity.Relationships) { %>
-<% if(r.ThisCardinality == Cardinality.Many) { %>
- public virtual ICollection<<%= r.OtherEntity.ToSafeName() %>> <%= r.ThisPropertyName.ToSafeName() %> { get; set; }
-<% } else { %>
- public virtual <%= r.OtherEntity.ToSafeName() %> <%= r.ThisPropertyName.ToSafeName() %> { get; set; }
-<% } %>
-<% } // foreach %>
+ /// <%=p.Description %>
+ ///
+ [Description("<%=p.Description%>")]
+ <%if(p.Name.LastIndexOf("Id") != -1){%>
+ [Browsable(false)]
+ <%}%>
+ <%if(p.DataType == DbType.Byte){%>
+ public bool <%= p.Name%> { get; set; }
+ <%}else{%>
+ public <%= p.SystemType.ToNullableType(p.AllowDBNull == true) %> <%= p.Name%> { get; set; }
+ <%}%>
+ <% } // foreach %>
}
}
\ No newline at end of file
diff --git a/CodeSmith/CSharp/Internal/Generator.cs b/CodeSmith/CSharp/Internal/Generator.cs
index c3ecd1c6e56b80693a214222e3e878deda50282f..a5e660e030975435f008efd476a590291ba7ab13 100644
--- a/CodeSmith/CSharp/Internal/Generator.cs
+++ b/CodeSmith/CSharp/Internal/Generator.cs
@@ -205,6 +205,27 @@ namespace SchemaMapper
get { return _settings; }
}
+ //按表信息创建DbContext
+ public EntityContext Generate(TableSchema tableSchema)
+ {
+ // only DeepLoad when in ignore mode
+ tableSchema.DeepLoad = !Settings.InclusionMode;
+
+ var entityContext = new EntityContext();
+ entityContext.DatabaseName = tableSchema.Database.Name;
+
+ string dataContextName = StringUtil.ToPascalCase(tableSchema.Database.Name) + "Context";
+ dataContextName = _namer.UniqueClassName(dataContextName);
+
+ entityContext.ClassName = dataContextName;
+
+ GetEntity(entityContext, tableSchema);
+
+
+ return entityContext;
+ }
+
+ //按数据库连接信息创建DbContext
public EntityContext Generate(DatabaseSchema databaseSchema)
{
// only DeepLoad when in ignore mode
@@ -240,8 +261,8 @@ namespace SchemaMapper
return entityContext;
}
-
- private Entity GetEntity(EntityContext entityContext, TableSchema tableSchema, bool processRelationships = true, bool processMethods = true)
+ //根据DbContext和tableSchema获取实体
+ public Entity GetEntity(EntityContext entityContext, TableSchema tableSchema, bool processRelationships = true, bool processMethods = true)
{
string key = tableSchema.FullName;
@@ -363,7 +384,7 @@ namespace SchemaMapper
if (Settings.IsIgnored(tableKey.ForeignKeyTable.FullName)
|| Settings.IsIgnored(tableKey.PrimaryKeyTable.FullName))
{
- Debug.WriteLine("Skipping relationship '{0}' because table '{1}' or '{2}' is ignored.",
+ Debug.WriteLine("Skipping relationship '{0}' because table '{1}' or '{2}' is ignored.",
tableKey.FullName, tableKey.ForeignKeyTable.FullName, tableKey.PrimaryKeyTable.FullName);
continue;
diff --git a/CodeSmith/CSharp/Internal/Mapping.Generated.cst b/CodeSmith/CSharp/Internal/Mapping.Generated.cst
deleted file mode 100644
index 8d59b7fdd5a524cf011400680f1d6c977562eca8..0000000000000000000000000000000000000000
--- a/CodeSmith/CSharp/Internal/Mapping.Generated.cst
+++ /dev/null
@@ -1,294 +0,0 @@
-<%@ Template Language="C#" TargetLanguage="C#" Debug="True" Encoding="UTF-8" %>
-
-<%@ Assembly Src="Model.cs" %>
-<%@ Assembly Src="Extensions.cs" %>
-
-<%@ Import Namespace="System.Collections.Generic" %>
-<%@ Import Namespace="System.Linq" %>
-<%@ Import Namespace="System.Text" %>
-<%@ Import Namespace="System.Text.RegularExpressions" %>
-
-<%@ Import Namespace="SchemaMapper" %>
-
-<%@ Property Name="Entity" Type="SchemaMapper.Entity" %>
-<%@ Property Name="ContextNamespace" Type="System.String" %>
-<%@ Property Name="EntityNamespace" Type="System.String" %>
-<%@ Property Name="MappingNamespace" Type="System.String" %>
-//------------------------------------------------------------------------------
-//
-// This code was generated by a CodeSmith Template.
-//
-// DO NOT MODIFY contents of this file. Changes to this
-// file will be lost if the code is regenerated.
-//
-//------------------------------------------------------------------------------
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations;
-
-namespace <%= MappingNamespace %>
-{
- public partial class <%= Entity.MappingName.ToSafeName() %>
- : System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<<%= EntityNamespace %>.<%= Entity.ClassName.ToSafeName() %>>
- {
- public <%= Entity.MappingName.ToSafeName() %>()
- {
- // table
-<% if (string.IsNullOrEmpty(Entity.TableSchema)) { %>
- ToTable("<%= Entity.TableName %>");
-<% } else { %>
- ToTable("<%= Entity.TableName %>", "<%= Entity.TableSchema %>");
-<% } %>
-
- // keys
-<% if (Entity.Properties.PrimaryKeys.Count() > 0) { %>
- HasKey(t => <%= KeyExpression(Entity.Properties.PrimaryKeys, "t") %>);
-<% } %>
-
- // Properties
-<%
-foreach(var p in Entity.Properties)
-{
- Response.Write(PropertyExpression(p));
-}
-%>
-
- // Relationships
-<%
-foreach(var r in Entity.Relationships.Where(e => e.IsMapped))
-{
- if (r.IsManyToMany)
- Response.Write(ManyToManyExpression(r));
- else
- Response.Write(RelationshipExpression(r));
-}
-%>
- }
- }
-}
-
-
\ No newline at end of file
diff --git a/CodeSmith/CSharp/Web/Controller.cst b/CodeSmith/CSharp/Web/Controller.cst
index 3858e30dcbd84885a6e4fdda6eedf689d26345c1..307d1fe01ac1638d340351eba626f678d08b913e 100644
--- a/CodeSmith/CSharp/Web/Controller.cst
+++ b/CodeSmith/CSharp/Web/Controller.cst
@@ -10,34 +10,39 @@ Description: Create a list of properties from a database table
<%@ Import Namespace="SchemaExplorer" %>
using System;
-using System.Web.Http;
-using System.Web.Mvc;
+using System.Collections.Generic;
+using System.Linq;
using Infrastructure;
+using Microsoft.AspNetCore.Mvc;
using OpenAuth.App;
+using OpenAuth.App.Interface;
using OpenAuth.App.Request;
-using OpenAuth.App.Response;
-using OpenAuth.Mvc.Models;
+using OpenAuth.Repository.Domain;
namespace OpenAuth.Mvc.Controllers
{
public class <%=ModuleName%>sController : BaseController
{
- public <%=ModuleName%>App App { get; set; }
+ private readonly <%=ModuleName%>App _app;
- //
- [Authenticate]
+ public <%=ModuleName%>sController(<%=ModuleName%>App app, IAuth auth) : base(auth)
+ {
+ _app = app;
+ }
+
+ //主页
public ActionResult Index()
{
return View();
}
//添加或修改
- [System.Web.Mvc.HttpPost]
+ [HttpPost]
public string Add(<%=ModuleName%> obj)
{
try
{
- App.Add(obj);
+ _app.Add(obj);
}
catch (Exception ex)
@@ -49,12 +54,12 @@ namespace OpenAuth.Mvc.Controllers
}
//添加或修改
- [System.Web.Mvc.HttpPost]
+ [HttpPost]
public string Update(<%=ModuleName%> obj)
{
try
{
- App.Update(obj);
+ _app.Update(obj);
}
catch (Exception ex)
@@ -68,17 +73,17 @@ namespace OpenAuth.Mvc.Controllers
///
/// 加载列表
///
- public string Load([FromUri]Query<%=ModuleName%>ListReq request)
+ public string Load([FromQuery]Query<%=ModuleName%>ListReq request)
{
- return JsonHelper.Instance.Serialize(App.Load(request));
+ return JsonHelper.Instance.Serialize(_app.Load(request));
}
- [System.Web.Mvc.HttpPost]
+ [HttpPost]
public string Delete(string[] ids)
{
try
{
- App.Delete(ids);
+ _app.Delete(ids);
}
catch (Exception e)
{
diff --git a/CodeSmith/CSharp/Web/Index.cshtml.cst b/CodeSmith/CSharp/Web/Index.cshtml.cst
index 4ff073c3c1c42a2313930bf8f69ba40af849c445..94c8e495e72c383b8a5c8d45a3d3e16facdca5a4 100644
--- a/CodeSmith/CSharp/Web/Index.cshtml.cst
+++ b/CodeSmith/CSharp/Web/Index.cshtml.cst
@@ -21,45 +21,34 @@ Description="连接的数据库" %>
-
-
-
-
-
-
- |
- <% foreach (ColumnSchema column in this.SourceTable.Columns) {%>
- <%=Tools.GetDescription(column)%> |
- <% }%>
- |
-
-
-
-
-
+
-
+
diff --git a/CodeSmith/CSharp/Web/index.js.cst b/CodeSmith/CSharp/Web/index.js.cst
index 89f5942b2d3c3b66eb962cef37f1cbdbdbedf2b5..85c54192687a6f320d6d87cc3e23c4c0e3722d9c 100644
--- a/CodeSmith/CSharp/Web/index.js.cst
+++ b/CodeSmith/CSharp/Web/index.js.cst
@@ -13,73 +13,63 @@ Author: yubaolee
layui.config({
base: "/js/"
-}).use(['form','vue', 'ztree', 'layer', 'jquery', 'table','droptree','openauth', 'utils'], function () {
+}).use(['form', 'vue', 'ztree', 'layer', 'jquery', 'table', 'droptree', 'openauth', 'utils'], function () {
var form = layui.form,
layer = layui.layer,
$ = layui.jquery;
var table = layui.table;
var openauth = layui.openauth;
var toplayer = (top == undefined || top.layer === undefined) ? layer : top.layer; //顶层的LAYER
- layui.droptree("/UserSession/GetOrgs", "#Organizations", "#OrganizationIds");
$("#menus").loadMenus("<%=ModuleName%>");
-
+
+
+ //加载表头
+ $.getJSON('/<%=ModuleName%>s/Load',
+ { page: 1, limit: 1 },
+ function (data) {
+ var columns = data.columnHeaders.map(function (e) {
+ return {
+ field: e.Key,
+ title: e.Description
+ };
+ });
+ columns.unshift({
+ type: 'checkbox',
+ fixed: 'left'
+ });
+ table.render({
+ elem: '#mainList',
+ page: true,
+ url: '/<%=ModuleName%>s/Load',
+ cols: [columns]
+ , response: {
+ statusCode: 200 //规定成功的状态码,默认:0
+ }
+ });
+ });
+
+
//主列表加载,可反复调用进行刷新
- var config= {}; //table的参数,如搜索key,点击tree的id
- var mainList = function (options) {
+ var config = {}; //table的参数,如搜索key,点击tree的id
+ var mainList = function(options) {
if (options != undefined) {
$.extend(config, options);
}
- table.reload('mainList', {
- url: '/<%=ModuleName%>s/Load',
- where: config
- });
- }
- //左边树状机构列表
- var ztree = function () {
- var url = '/UserSession/GetOrgs';
- var zTreeObj;
- var setting = {
- view: { selectedMulti: false },
- data: {
- key: {
- name: 'Name',
- title: 'Name'
- },
- simpleData: {
- enable: true,
- idKey: 'Id',
- pIdKey: 'ParentId',
- rootPId: 'null'
- }
- },
- callback: {
- onClick: function (event, treeId, treeNode) {
- mainList({ orgId: treeNode.Id });
- }
- }
- };
- var load = function () {
- $.getJSON(url, function (json) {
- zTreeObj = $.fn.zTree.init($("#tree"), setting);
- var newNode = { Name: "根节点", Id: null, ParentId: "" };
- json.push(newNode);
- zTreeObj.addNodes(null, json);
- mainList({ orgId: "" });
- zTreeObj.expandAll(true);
+ table.reload('mainList',
+ {
+ url: '/<%=ModuleName%>s/Load',
+ where: config
+ , response: {
+ statusCode: 200 //规定成功的状态码,默认:0
+ }
});
- };
- load();
- return {
- reload: load
- }
- }();
-
+ };
+ mainList();
+
//添加(编辑)对话框
- var editDlg = function() {
- var vm = new Vue({
- el: "#formEdit"
- });
+ var editDlg = function () {
+ var vm;
var update = false; //是否为更新
var show = function (data) {
var title = update ? "编辑信息" : "添加";
@@ -88,21 +78,46 @@ layui.config({
area: ["500px", "400px"],
type: 1,
content: $('#divEdit'),
- success: function() {
- vm.$set('$data', data);
+ success: function () {
+ if(vm == undefined){
+ vm = new Vue({
+ el: "#formEdit",
+ data(){
+ return {
+ tmp:data //使用一个tmp封装一下,后面可以直接用vm.tmp赋值
+ }
+ },
+ watch:{
+ tmp(val){
+ this.$nextTick(function () {
+ form.render(); //刷新select等
+ layui.droptree("/Applications/GetList", "#AppName", "#AppId", false);
+
+ })
+ }
+ },
+ mounted(){
+ form.render();
+ layui.droptree("/Applications/GetList", "#AppName", "#AppId", false);
+
+ }
+ });
+ }else{
+ vm.tmp = Object.assign({}, vm.tmp,data)
+ }
},
end: mainList
});
var url = "/<%=ModuleName%>s/Add";
if (update) {
- url = "/<%=ModuleName%>s/Update";
+ url = "/<%=ModuleName%>s/Update";
}
//提交数据
form.on('submit(formSubmit)',
- function(data) {
+ function (data) {
$.post(url,
data.field,
- function(data) {
+ function (data) {
layer.msg(data.Message);
},
"json");
@@ -110,25 +125,25 @@ layui.config({
});
}
return {
- add: function() { //弹出添加
+ add: function () { //弹出添加
update = false;
show({
Id: ''
});
},
- update: function(data) { //弹出编辑框
+ update: function (data) { //弹出编辑框
update = true;
show(data);
}
};
}();
-
+
//监听表格内部按钮
table.on('tool(list)', function (obj) {
var data = obj.data;
if (obj.event === 'detail') { //查看
layer.msg('ID:' + data.Id + ' 的查看操作');
- }
+ }
});
@@ -144,20 +159,20 @@ layui.config({
, btnAdd: function () { //添加
editDlg.add();
}
- , btnEdit: function () { //编辑
- var checkStatus = table.checkStatus('mainList')
- , data = checkStatus.data;
- if (data.length != 1) {
- layer.msg("请选择编辑的行,且同时只能编辑一行");
- return;
- }
- editDlg.update(data[0]);
- }
+ , btnEdit: function () { //编辑
+ var checkStatus = table.checkStatus('mainList')
+ , data = checkStatus.data;
+ if (data.length != 1) {
+ layer.msg("请选择编辑的行,且同时只能编辑一行");
+ return;
+ }
+ editDlg.update(data[0]);
+ }
, search: function () { //搜索
mainList({ key: $('#key').val() });
}
- , btnRefresh: function() {
+ , btnRefresh: function () {
mainList();
}
};
@@ -168,4 +183,4 @@ layui.config({
});
//监听页面主按钮操作 end
-})
\ No newline at end of file
+})
diff --git a/CodeSmith/CSharp/WebGenerate.cst b/CodeSmith/CSharp/WebGenerate.cst
index 026d729078dbe6d31f4732171a6712ab71f62a0c..01b04d5a3fe3b2db956bbad5837c04287e2316fa 100644
--- a/CodeSmith/CSharp/WebGenerate.cst
+++ b/CodeSmith/CSharp/WebGenerate.cst
@@ -1,4 +1,8 @@
-<%@ Template Language="C#" TargetLanguage="Text" Debug="True" OutputType="None" %>
+<%--
+Author: yubaolee
+Description: 用于生成OpenAuth.Core开源版前端Web界面,包括mvc controller/csthml/js
+--%>
+<%@ Template Language="C#" TargetLanguage="Text" Debug="True" OutputType="None" %>
<%@ Assembly Name="SchemaExplorer" %>
<%@ Assembly Name="CodeSmith.CustomProperties" %>
@@ -36,12 +40,6 @@ OnChanged="OnSourceDatabaseChanged"%>
Description="代码生成路径"
Editor="System.Windows.Forms.Design.FolderNameEditor, System.Design, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" %>
-<%@ Register Name="ApplicationGenerateClass"
- Template="Web\Application.cst"
- MergeProperties="False" %>
-<%@ Register Name="RequestGenerateClass"
- Template="Web\Request.cst"
- MergeProperties="False" %>
<%@ Register Name="HtmlGenerateClass"
Template="Web\Index.cshtml.cst"
MergeProperties="False" %>
@@ -61,8 +59,6 @@ Generating Entities ...
string outputDirectory = Path.GetFullPath(directory);
CreateControllerClass();
- CreateApplicationClass();
- CreateReqClass();
CreateHtmlClass();
CreateJSClass();
@@ -84,23 +80,7 @@ Generating Entities ...
string rootDirectory = Path.GetFullPath(directory);
- string generatedFile = Path.GetFullPath(directory) + "/controllers/"+ ModuleName + "sController.cs";
-
- generatedClass.ModuleName = ModuleName;
-
- Response.WriteLine(generatedFile);
- generatedClass.RenderToFile(generatedFile, generatedFile, true);
- }
-
- //创建APP层,如UserManagerApp.cs
- public void CreateApplicationClass()
- {
- ApplicationGenerateClass generatedClass = this.Create();
- this.CopyPropertiesTo(generatedClass);
-
- string rootDirectory = Path.GetFullPath(directory);
-
- string generatedFile = Path.GetFullPath(directory) + "/APP/"+ ModuleName + "App.cs";
+ string generatedFile = Path.GetFullPath(directory) + "/Controllers/"+ ModuleName + "sController.cs";
generatedClass.ModuleName = ModuleName;
@@ -108,22 +88,6 @@ Generating Entities ...
generatedClass.RenderToFile(generatedFile, generatedFile, true);
}
-
- //创建请求参数,如QueryUserListReq.cs
- public void CreateReqClass()
- {
- RequestGenerateClass generatedClass = this.Create();
- this.CopyPropertiesTo(generatedClass);
-
- string rootDirectory = Path.GetFullPath(directory);
-
- string generatedFile = Path.GetFullPath(directory) + "/APP/Request/Query"+ ModuleName + "ListReq.cs";
-
- generatedClass.ModuleName = ModuleName;
-
- Response.WriteLine(generatedFile);
- generatedClass.RenderToFile(generatedFile, generatedFile, true);
- }
//创建视图,如views/Users/index.html
public void CreateHtmlClass()
@@ -131,7 +95,7 @@ Generating Entities ...
HtmlGenerateClass generatedClass = this.Create();
this.CopyPropertiesTo(generatedClass);
- string generatedFile = Path.GetFullPath(directory) + "/views/"+ModuleName+"s/index.cshtml";
+ string generatedFile = Path.GetFullPath(directory) + "/Views/"+ModuleName+"s/index.cshtml";
generatedClass.ModuleName = ModuleName;
generatedClass.SourceTable = SourceTable;
@@ -158,7 +122,7 @@ Generating Entities ...
//更换数据源时,改变ModuleName
private void OnSourceDatabaseChanged(object sender, EventArgs e)
{
- if (SourceTable == null || ModuleName != null)
+ if (SourceTable == null)
return;
ModuleName = SourceTable.Name;
}
diff --git a/Infrastructure/AutoMapperExt.cs b/Infrastructure/AutoMapperExt.cs
index b0d99bf6cadb41f78d4719d7096ce482196a2d64..13fc941620a398e0876334c617f296880487c2d5 100644
--- a/Infrastructure/AutoMapperExt.cs
+++ b/Infrastructure/AutoMapperExt.cs
@@ -12,10 +12,10 @@
//
// ***********************************************************************
+using System;
using AutoMapper;
using System.Collections;
using System.Collections.Generic;
-using System.Data;
namespace Infrastructure
{
@@ -27,8 +27,10 @@ namespace Infrastructure
public static T MapTo(this object obj)
{
if (obj == null) return default(T);
- Mapper.CreateMap(obj.GetType(), typeof(T));
- return Mapper.Map(obj);
+
+ var config = new MapperConfiguration(cfg=>cfg.CreateMap(obj.GetType(),typeof(T)));
+ var mapper = config.CreateMapper();
+ return mapper.Map(obj);
}
///
@@ -36,13 +38,11 @@ namespace Infrastructure
///
public static List MapToList(this IEnumerable source)
{
- foreach (var first in source)
- {
- var type = first.GetType();
- Mapper.CreateMap(type, typeof(TDestination));
- break;
- }
- return Mapper.Map>(source);
+ Type sourceType = source.GetType().GetGenericArguments()[0]; //获取枚举的成员类型
+ var config = new MapperConfiguration(cfg => cfg.CreateMap(sourceType, typeof(TDestination)));
+ var mapper = config.CreateMapper();
+
+ return mapper.Map>(source);
}
///
@@ -50,9 +50,10 @@ namespace Infrastructure
///
public static List MapToList(this IEnumerable source)
{
- //IEnumerable 类型需要创建元素的映射
- Mapper.CreateMap();
- return Mapper.Map>(source);
+ var config = new MapperConfiguration(cfg => cfg.CreateMap(typeof(TSource), typeof(TDestination)));
+ var mapper = config.CreateMapper();
+
+ return mapper.Map>(source);
}
///
@@ -63,18 +64,11 @@ namespace Infrastructure
where TDestination : class
{
if (source == null) return destination;
- Mapper.CreateMap();
- return Mapper.Map(source, destination);
- }
- ///
- /// DataReader映射
- ///
- public static IEnumerable DataReaderMapTo(this IDataReader reader)
- {
- Mapper.Reset();
- Mapper.CreateMap>();
- return Mapper.Map>(reader);
+ var config = new MapperConfiguration(cfg => cfg.CreateMap(typeof(TSource), typeof(TDestination)));
+ var mapper = config.CreateMapper();
+ return mapper.Map(source);
}
+
}
}
\ No newline at end of file
diff --git a/Infrastructure/Cache/CacheContext.cs b/Infrastructure/Cache/CacheContext.cs
index f063e6fecd7366a046fcb711ed0472241ec7dc80..a7670f7096e5a64c41158f3525b3e74793a95b17 100644
--- a/Infrastructure/Cache/CacheContext.cs
+++ b/Infrastructure/Cache/CacheContext.cs
@@ -10,17 +10,22 @@
// ***********************************************************************
using System;
-using System.Web;
+using Microsoft.Extensions.Caching.Memory;
namespace Infrastructure.Cache
{
public class CacheContext : ICacheContext
{
- private readonly System.Web.Caching.Cache _objCache = HttpRuntime.Cache;
+ private IMemoryCache _objCache;
+
+ public CacheContext(IMemoryCache objCache)
+ {
+ _objCache = objCache;
+ }
+
public override T Get(string key)
{
- System.Web.Caching.Cache objCache = HttpRuntime.Cache;
- return (T) objCache[key];
+ return _objCache.Get(key);
}
public override bool Set(string key, T t, DateTime expire)
@@ -30,8 +35,10 @@ namespace Infrastructure.Cache
{
Remove(key);
}
-
- _objCache.Insert(key, t, null, expire, System.Web.Caching.Cache.NoSlidingExpiration);
+
+ _objCache.Set(key, t, new MemoryCacheEntryOptions()
+ .SetAbsoluteExpiration(expire)); //绝对过期时间
+
return true;
}
diff --git a/Infrastructure/Cache/CacheProvider.cs b/Infrastructure/Cache/CacheProvider.cs
deleted file mode 100644
index 18c0255b754dd0aaf3d029f0394b2bc9142e9346..0000000000000000000000000000000000000000
--- a/Infrastructure/Cache/CacheProvider.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-using System;
-using System.Globalization;
-
-namespace Infrastructure.Cache
-{
- ///
- /// 缓存工厂
- /// 李玉宝新增于2016-11-09 9:42:52
- ///
- public abstract class CacheProvider : IDisposable
- {
- ///
- /// 缓存组件
- ///
- public ICacheContext CacheContext { get; private set; }
-
- ///
- /// 动态设置缓存对象的新实例
- ///
- /// 缓存实例对象
- public void SetCacheInstance(ICacheContext cacheContext)
- {
- //先释放现有的缓存组件
- if (CacheContext != null)
- {
- CacheContext = null;
- }
-
- //初始化缓存组件新的实例
- CacheContext = cacheContext;
- }
-
- public void SetCacheInstance(Type cacheContextType)
- {
- if (cacheContextType == null)
- {
- throw new ArgumentNullException("cacheContextType");
- }
-
- if (!typeof(ICacheContext).IsAssignableFrom(cacheContextType))
- {
- throw new ArgumentException(
- string.Format(CultureInfo.CurrentCulture, "该类型 {0} 必须继承自抽象类CacheContext", cacheContextType),
- "cacheContextType");
- }
-
- try
- {
- CacheContext = Activator.CreateInstance(cacheContextType) as ICacheContext;
- }
- catch (Exception ex)
- {
- throw new InvalidOperationException(
- String.Format(
- CultureInfo.CurrentCulture,
- "创建抽象类 CacheContext 的实例 {0} 失败",
- cacheContextType),
- ex);
- }
- }
-
- public void Dispose()
- {
-
- }
- }
-}
diff --git a/Infrastructure/Cache/EnyimMemcachedContext.cs b/Infrastructure/Cache/EnyimMemcachedContext.cs
index 64640dcf58292ede9bb9e286f001746df6eedee0..e12fb2e2c78e7562687d6764ae282fd62c963dec 100644
--- a/Infrastructure/Cache/EnyimMemcachedContext.cs
+++ b/Infrastructure/Cache/EnyimMemcachedContext.cs
@@ -5,11 +5,13 @@
//
// Last Modified By : yubaolee
// Last Modified On : 06-21-2016
-// Contact :
+// Contact : Add services.AddEnyimMemcached(...)
+// and app.UseEnyimMemcached() in Startup.
// File: EnyimMemcachedContext.cs
// ***********************************************************************
+
using System;
using Enyim.Caching;
using Enyim.Caching.Memcached;
@@ -18,7 +20,12 @@ namespace Infrastructure.Cache
{
public sealed class EnyimMemcachedContext : ICacheContext
{
- private static readonly MemcachedClient _memcachedClient = new MemcachedClient();
+ private IMemcachedClient _memcachedClient;
+
+ public EnyimMemcachedContext(IMemcachedClient client)
+ {
+ _memcachedClient = client;
+ }
public override T Get(string key)
{
diff --git a/Infrastructure/Cache/ObjCacheProvider.cs b/Infrastructure/Cache/ObjCacheProvider.cs
deleted file mode 100644
index 127158fc6d9dc26f4ae4e2c04659676d93b95498..0000000000000000000000000000000000000000
--- a/Infrastructure/Cache/ObjCacheProvider.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-// ***********************************************************************
-// Assembly : Helper
-// Author : Administrator
-// Created : 12-21-2016
-//
-// Last Modified By : Administrator
-// Last Modified On : 12-22-2016
-// Contact :
-// File: ObjCacheProvider.cs
-// ***********************************************************************
-
-
-using System;
-
-namespace Infrastructure.Cache
-{
- ///
- /// 缓存工厂实现
- /// 这样做是方便换其他的缓存时(如memcachedContext)只换这一个地方即可
- ///
- public class ObjCacheProvider : CacheProvider
- {
- public ObjCacheProvider()
- {
- SetCacheInstance(new CacheContext());
- }
-
- public bool Create(string key, T val, DateTime expire)
- {
- //设置缓存
- return CacheContext.Set(key, val, expire);
- }
-
- ///
- /// 根据失效时间获取缓存
- /// 李玉宝于2016-11-08 16:54:04
- ///
- /// The key.
- public T GetCache(string key)
- {
- return CacheContext.Get(key);
- }
-
- public void Remove(string key)
- {
- CacheContext.Remove(key);
- }
- }
-}
\ No newline at end of file
diff --git a/Infrastructure/CommonException.cs b/Infrastructure/CommonException.cs
new file mode 100644
index 0000000000000000000000000000000000000000..32e0cc242649287d2dd55b7fc93436f6d5412ea7
--- /dev/null
+++ b/Infrastructure/CommonException.cs
@@ -0,0 +1,22 @@
+
+using System;
+
+namespace Infrastructure
+{
+ public class CommonException : Exception
+ {
+ private int _code;
+
+ public CommonException(string message, int code)
+ : base(message)
+ {
+ this._code = code;
+ }
+
+ public int Code
+ {
+ get { return _code; }
+ }
+
+ }
+}
diff --git a/Infrastructure/Const/HtmlElementType.cs b/Infrastructure/Const/HtmlElementType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..0389706c148421af320eb26933c18aed280c7207
--- /dev/null
+++ b/Infrastructure/Const/HtmlElementType.cs
@@ -0,0 +1,26 @@
+namespace Infrastructure.Const
+{
+ public struct HtmlElementType
+ {
+ public const string drop = "drop";
+ public const string droplist = "droplist";
+ public const string select = "select";
+ public const string selectlist = "selectlist";
+ public const string checkbox = "checkbox";
+ public const string textarea = "textarea";
+ public const string thanorequal = "thanorequal";
+ public const string lessorequal = "lessorequal";
+
+
+ public const string gt = "gt";
+ public const string lt = "lt";
+ public const string GT = ">";
+ public const string LT = "<";
+ public const string like = "like";
+
+ public const string ThanOrEqual = ">=";
+ public const string LessOrequal = "<=";
+ public const string Contains = "in";
+ public const string Equal = "=";
+ }
+}
\ No newline at end of file
diff --git a/Infrastructure/Const/LinqExpressionType.cs b/Infrastructure/Const/LinqExpressionType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..ecc32e2daedb66a1c585da917b431b84dbe8301a
--- /dev/null
+++ b/Infrastructure/Const/LinqExpressionType.cs
@@ -0,0 +1,15 @@
+namespace Infrastructure.Const
+{
+ public enum LinqExpressionType
+ {
+ Equal=0,//=
+ NotEqual=1,//!=
+ GreaterThan,//>
+ LessThan,//<
+ ThanOrEqual,//>=
+ LessThanOrEqual,//<=
+ In,
+ Contains,//Contains
+ NotContains//NotContains
+ }
+}
diff --git a/Infrastructure/Const/QueryOrderBy.cs b/Infrastructure/Const/QueryOrderBy.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f40970777d480f512cead1be10a3acc99144b1fe
--- /dev/null
+++ b/Infrastructure/Const/QueryOrderBy.cs
@@ -0,0 +1,8 @@
+namespace Infrastructure.Const
+{
+ public enum QueryOrderBy
+ {
+ Desc=1,
+ Asc=2
+ }
+}
diff --git a/Infrastructure/Const/ResponseType.cs b/Infrastructure/Const/ResponseType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1552f90c042b243c34f95de4e4d4157e61fe78e5
--- /dev/null
+++ b/Infrastructure/Const/ResponseType.cs
@@ -0,0 +1,27 @@
+namespace Infrastructure.Const
+{
+ public enum ResponseType
+ {
+ ServerError = 1,
+ LoginExpiration = 302,
+ ParametersLack = 303,
+ TokenExpiration,
+ PINError,
+ NoPermissions,
+ NoRolePermissions,
+ LoginError,
+ AccountLocked,
+ LoginSuccess,
+ SaveSuccess,
+ AuditSuccess,
+ OperSuccess,
+ RegisterSuccess,
+ ModifyPwdSuccess,
+ EidtSuccess,
+ DelSuccess,
+ NoKey,
+ NoKeyDel,
+ KeyError,
+ Other
+ }
+}
diff --git a/Infrastructure/Const/SqlDbTypeName.cs b/Infrastructure/Const/SqlDbTypeName.cs
new file mode 100644
index 0000000000000000000000000000000000000000..2bc9bc723df311354d9d8e2ee23590f20e4877f7
--- /dev/null
+++ b/Infrastructure/Const/SqlDbTypeName.cs
@@ -0,0 +1,24 @@
+namespace Infrastructure.Const
+{
+ public struct SqlDbTypeName
+ {
+ public const string NVarChar = "nvarchar";
+ public const string VarChar = "varchar";
+ public const string NChar = "nchar";
+ public const string Char = "char";
+ public const string Text = "text";
+ public const string Int = "int";
+ public const string BigInt = "bigint";
+ public const string DateTime = "datetime";
+ public const string Date = "date";
+ public const string SmallDateTime = "smalldatetime";
+ public const string SmallDate = "smalldate";
+ public const string Float = "float";
+ public const string Decimal = "decimal";
+ public const string Double = "double";
+ public const string Bit = "bit";
+ public const string Bool = "bool";
+ public const string UniqueIdentifier = "uniqueidentifier";
+
+ }
+}
diff --git a/Infrastructure/CookieHelper.cs b/Infrastructure/CookieHelper.cs
deleted file mode 100644
index 11ce0b82d8d3ee6c5e89cc759126ac999e2c40ab..0000000000000000000000000000000000000000
--- a/Infrastructure/CookieHelper.cs
+++ /dev/null
@@ -1,112 +0,0 @@
-// ***********************************************************************
-// Assembly : Infrastructure
-// Author : Administrator
-// Created : 09-22-2015
-//
-// ***********************************************************************
-//
-// Copyright (c) . All rights reserved.
-//
-// Cookie辅助
-// ***********************************************************************
-
-using System;
-using System.Web;
-
-namespace Infrastructure
-{
- ///
- /// Cookie帮助类
- ///
- public class CookieHelper
- {
- ///
- /// 写cookie值
- ///
- /// 名称
- /// 值
- public static void WriteCookie(string strName, string strValue)
- {
- HttpCookie cookie = HttpContext.Current.Request.Cookies[strName];
- if (cookie == null)
- {
- cookie = new HttpCookie(strName);
- }
- cookie.Value = strValue;
- HttpContext.Current.Response.AppendCookie(cookie);
-
- }
- ///
- /// 写cookie值
- ///
- /// 名称
- /// 值
- /// 过期时间(分钟)
- public static void WriteCookie(string strName, string strValue, int expires)
- {
- HttpCookie cookie = HttpContext.Current.Request.Cookies[strName];
- if (cookie == null)
- {
- cookie = new HttpCookie(strName);
- }
- cookie.Value = strValue;
- cookie.Expires = DateTime.Now.AddMinutes(expires);
- HttpContext.Current.Response.AppendCookie(cookie);
-
- }
-
- ///
- /// 读cookie值
- ///
- /// 名称
- /// cookie值
- public static string GetCookie(string strName)
- {
- if (HttpContext.Current.Request.Cookies[strName] != null)
- {
- return HttpContext.Current.Request.Cookies[strName].Value.ToString();
- }
- return "";
- }
-
- ///
- /// Get cookie expiry date that was set in the cookie value
- ///
- ///
- ///
- public static DateTime GetExpirationDate(HttpCookie cookie)
- {
- if (String.IsNullOrEmpty(cookie.Value))
- {
- return DateTime.MinValue;
- }
- string strDateTime = cookie.Value.Substring(cookie.Value.IndexOf("|") + 1);
- return Convert.ToDateTime(strDateTime);
- }
-
- ///
- /// Set cookie value using the token and the expiry date
- ///
- ///
- ///
- ///
- public static string BuildCookueValue(string value, int minutes)
- {
- return String.Format("{0}|{1}", value, DateTime.Now.AddMinutes(minutes).ToString());
- }
-
- ///
- /// Reads cookie value from the cookie
- ///
- ///
- ///
- public static string GetCookieValue(HttpCookie cookie)
- {
- if (String.IsNullOrEmpty(cookie.Value))
- {
- return cookie.Value;
- }
- return cookie.Value.Substring(0, cookie.Value.IndexOf("|"));
- }
- }
-}
diff --git a/Infrastructure/DynamicLinq.cs b/Infrastructure/DynamicLinq.cs
index 1f3c16c949c1fc85f24fd9495a85124fb87df72d..8f334dcf8a28e0cc2c3833e17e814fa7a5f770b5 100644
--- a/Infrastructure/DynamicLinq.cs
+++ b/Infrastructure/DynamicLinq.cs
@@ -34,43 +34,51 @@ namespace Infrastructure
{
PropertyInfo property = typeof(T).GetProperty(filterObj.Key);
- //组装左边
- Expression left = Expression.Property(param, property);
+ Expression left = null; //组装左边
//组装右边
Expression right = null;
- if (property.PropertyType == typeof(int))
+ if (property != null)
{
- right = Expression.Constant(int.Parse(filterObj.Value));
- }
- else if (property.PropertyType == typeof(DateTime))
- {
- right = Expression.Constant(DateTime.Parse(filterObj.Value));
- }
- else if (property.PropertyType == typeof(string))
- {
- right = Expression.Constant((filterObj.Value));
- }
- else if (property.PropertyType == typeof(decimal))
- {
- right = Expression.Constant(decimal.Parse(filterObj.Value));
- }
- else if (property.PropertyType == typeof(Guid))
- {
- right = Expression.Constant(Guid.Parse(filterObj.Value));
- }
- else if (property.PropertyType == typeof(bool))
- {
- right = Expression.Constant(filterObj.Value.Equals("1"));
- }
- else if (property.PropertyType == typeof(Guid?))
- {
- left = Expression.Property(left, "Value");
- right = Expression.Constant(Guid.Parse(filterObj.Value));
+ left = Expression.Property(param, property);
+ if (property.PropertyType == typeof(int))
+ {
+ right = Expression.Constant(int.Parse(filterObj.Value));
+ }
+ else if (property.PropertyType == typeof(DateTime))
+ {
+ right = Expression.Constant(DateTime.Parse(filterObj.Value));
+ }
+ else if (property.PropertyType == typeof(string))
+ {
+ right = Expression.Constant(filterObj.Value);
+ }
+ else if (property.PropertyType == typeof(decimal))
+ {
+ right = Expression.Constant(decimal.Parse(filterObj.Value));
+ }
+ else if (property.PropertyType == typeof(Guid))
+ {
+ right = Expression.Constant(Guid.Parse(filterObj.Value));
+ }
+ else if (property.PropertyType == typeof(bool))
+ {
+ right = Expression.Constant(filterObj.Value.Equals("1"));
+ }
+ else if (property.PropertyType == typeof(Guid?))
+ {
+ left = Expression.Property(left, "Value");
+ right = Expression.Constant(Guid.Parse(filterObj.Value));
+ }
+ else
+ {
+ throw new Exception("暂不能解析该Key的类型");
+ }
}
- else
+ else //如果左边不是属性,直接是值的情况
{
- throw new Exception("暂不能解析该Key的类型");
+ left = Expression.Constant(filterObj.Key);
+ right = Expression.Constant(filterObj.Value);
}
//c.XXX=="XXX"
@@ -95,20 +103,33 @@ namespace Infrastructure
case "!=":
filter = Expression.NotEqual(left, right);
break;
-
- case "like":
- filter = Expression.Call(left, typeof(string).GetMethod("Contains", new Type[] { typeof(string) }),
- Expression.Constant(filterObj.Value));
+ case "contains":
+ filter = Expression.Call(left, typeof(string).GetMethod("Contains", new Type[] {typeof(string)}),
+ Expression.Constant(filterObj.Value));
+ break;
+ case "in":
+ var lExp = Expression.Constant(filterObj.Value.Split(',').ToList()); //数组
+ var methodInfo = typeof(List).GetMethod("Contains",
+ new Type[] {typeof(string)}); //Contains语句
+ filter = Expression.Call(lExp, methodInfo, left);
break;
case "not in":
var listExpression = Expression.Constant(filterObj.Value.Split(',').ToList()); //数组
- var method = typeof(List).GetMethod("Contains", new Type[] { typeof(string) }); //Contains语句
+ var method = typeof(List).GetMethod("Contains", new Type[] {typeof(string)}); //Contains语句
filter = Expression.Not(Expression.Call(listExpression, method, left));
break;
- case "in":
- var lExp = Expression.Constant(filterObj.Value.Split(',').ToList()); //数组
- var methodInfo = typeof(List).GetMethod("Contains", new Type[] { typeof(string) }); //Contains语句
- filter = Expression.Call(lExp, methodInfo, left);
+ //交集,使用交集时左值必须时固定的值
+ case "intersect": //交集
+ if (property != null)
+ {
+ throw new Exception("交集模式下,表达式左边不能为变量,请调整数据规则,如:c=>\"A,B,C\" intersect \"B,D\"");
+ }
+
+ var rightval = filterObj.Value.Split(',').ToList();
+ var leftval = filterObj.Key.Split(',').ToList();
+ var val = rightval.Intersect(leftval);
+
+ filter = Expression.Constant(val.Count() > 0);
break;
}
@@ -117,7 +138,7 @@ namespace Infrastructure
public static Expression> GenerateTypeBody(this ParameterExpression param, Filter filterObj)
{
- return (Expression>)(param.GenerateBody(filterObj));
+ return (Expression>) (param.GenerateBody(filterObj));
}
///
@@ -131,7 +152,7 @@ namespace Infrastructure
public static Expression> GenerateTypeLambda(this ParameterExpression param, Expression body)
{
- return (Expression>)(param.GenerateLambda(body));
+ return (Expression>) (param.GenerateLambda(body));
}
public static Expression AndAlso(this Expression expression, Expression expressionRight)
@@ -149,32 +170,137 @@ namespace Infrastructure
return Expression.And(expression, expressionRight);
}
- //系统已经有该函数的实现
- //public static IQueryable Where(this IQueryable query, Expression expression)
- //{
- // Expression expr = Expression.Call(typeof(Queryable), "Where", new[] { typeof(T) },
- // Expression.Constant(query), expression);
- // //生成动态查询
- // IQueryable result = query.Provider.CreateQuery(expr);
- // return result;
- //}
-
- public static IQueryable GenerateFilter(this IQueryable query, string filterjson)
+ public static IQueryable GenerateFilter(this IQueryable query, string parametername, string filterjson)
{
if (!string.IsNullOrEmpty(filterjson))
{
- var filters = JsonHelper.Instance.Deserialize>(filterjson);
- var param = CreateLambdaParam("c");
+ var filterGroup = JsonHelper.Instance.Deserialize(filterjson);
+ query = GenerateFilter(query, parametername, filterGroup);
+ }
+
+ return query;
+ }
+
+ ///
+ /// 转换FilterGroup为Lambda表达式
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static IQueryable GenerateFilter(this IQueryable query, string parametername,
+ FilterGroup filterGroup)
+ {
+ var param = CreateLambdaParam(parametername);
+ Expression result = ConvertGroup(filterGroup, param);
+ query = query.Where(param.GenerateTypeLambda(result));
+ return query;
+ }
+
+ ///
+ /// 转换filtergroup为表达式
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Expression ConvertGroup(FilterGroup filterGroup, ParameterExpression param)
+ {
+ if (filterGroup == null) return null;
+
+ if (filterGroup.Filters.Length == 1 &&(filterGroup.Children == null || !filterGroup.Children.Any())) //只有一个条件
+ {
+ return param.GenerateBody(filterGroup.Filters[0]);
+ }
+
+ Expression result = ConvertFilters(filterGroup.Filters, param, filterGroup.Operation);
+ Expression gresult = ConvertGroup(filterGroup.Children, param, filterGroup.Operation);
+ if (gresult == null) return result;
+ if (result == null) return gresult;
+
+ if (filterGroup.Operation == "and")
+ {
+ return result.AndAlso(gresult);
+ }
+ else //or
+ {
+ return result.Or(gresult);
+ }
+ }
- Expression result = Expression.Constant(true);
- foreach (var filter in filters)
+ ///
+ /// 转换FilterGroup[]为表达式,不管FilterGroup里面的Filters
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static Expression ConvertGroup(FilterGroup[] groups, ParameterExpression param, string operation)
+ {
+ if (groups == null || !groups.Any()) return null;
+
+ Expression result = ConvertGroup(groups[0], param);
+
+ if (groups.Length == 1) return result;
+
+ if (operation == "and")
+ {
+ foreach (var filter in groups.Skip(1))
{
- result = result.AndAlso(param.GenerateBody(filter));
+ result = result.AndAlso(ConvertGroup(filter, param));
+ }
+ }
+ else
+ {
+ foreach (var filter in groups.Skip(1))
+ {
+ result = result.Or(ConvertGroup(filter, param));
}
+ }
+
+ return result;
+ }
- query = query.Where(param.GenerateTypeLambda(result));
+ ///
+ /// 转换Filter数组为表达式
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static Expression ConvertFilters(Filter[] filters, ParameterExpression param, string operation)
+ {
+ if (filters == null || !filters.Any())
+ {
+ return null;
}
- return query;
+
+ Expression result = param.GenerateBody(filters[0]);
+
+ if (filters.Length == 1)
+ {
+ return result;
+ }
+
+ if (operation == "and")
+ {
+ foreach (var filter in filters.Skip(1))
+ {
+ result = result.AndAlso(param.GenerateBody(filter));
+ }
+ }
+ else
+ {
+ foreach (var filter in filters.Skip(1))
+ {
+ result = result.Or(param.GenerateBody(filter));
+ }
+ }
+
+ return result;
}
}
}
\ No newline at end of file
diff --git a/Infrastructure/DynamicQueryable.cs b/Infrastructure/DynamicQueryable.cs
index 7b6da375fb3ece4cb32983b938a1cfca666d5549..5dc7afc39a14d83e9388cd3caf8d51e1dbb46332 100644
--- a/Infrastructure/DynamicQueryable.cs
+++ b/Infrastructure/DynamicQueryable.cs
@@ -277,7 +277,8 @@ namespace Infrastructure
private ClassFactory() {
AssemblyName name = new AssemblyName("DynamicClasses");
- AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
+ AssemblyBuilder assembly = AssemblyBuilder.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
+ // AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
#if ENABLE_LINQ_PARTIAL_TRUST
new ReflectionPermission(PermissionState.Unrestricted).Assert();
#endif
@@ -300,7 +301,10 @@ namespace Infrastructure
Type type;
if (!classes.TryGetValue(signature, out type)) {
type = CreateDynamicClass(signature.properties);
- classes.Add(signature, type);
+ //fixed by https://gitee.com/DUWENINK
+ if (!classes.ContainsKey(signature)){
+ classes.Add(signature, type);
+ }
}
return type;
}
diff --git a/Infrastructure/Extensions/AutofacManager/AutofacContainerModule.cs b/Infrastructure/Extensions/AutofacManager/AutofacContainerModule.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b29053f65644900482ab325f0051d52e116d871c
--- /dev/null
+++ b/Infrastructure/Extensions/AutofacManager/AutofacContainerModule.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace Infrastructure.Extensions.AutofacManager
+{
+ ///
+ /// 提供全局静态获取服务的能力。
+ /// 例:AutofacContainerModule.GetService()
+ ///
+ public class AutofacContainerModule
+ {
+ static private IServiceProvider _provider;
+ public static void ConfigServiceProvider(IServiceProvider serviceProvider)
+ {
+ _provider = serviceProvider;
+ }
+ public static TService GetService() where TService:class
+ {
+ Type typeParameterType = typeof(TService);
+ return (TService)_provider.GetService(typeParameterType);
+ }
+ }
+}
diff --git a/Infrastructure/Extensions/AutofacManager/IDependency.cs b/Infrastructure/Extensions/AutofacManager/IDependency.cs
new file mode 100644
index 0000000000000000000000000000000000000000..638e254fc22602d4a7c3a443956e3cf8e7961ed9
--- /dev/null
+++ b/Infrastructure/Extensions/AutofacManager/IDependency.cs
@@ -0,0 +1,9 @@
+namespace Infrastructure.Extensions.AutofacManager
+{
+ ///
+ /// 所有AutoFac注入的基类
+ ///
+ public interface IDependency
+ {
+ }
+}
diff --git a/Infrastructure/Extensions/ConvertJsonExtension.cs b/Infrastructure/Extensions/ConvertJsonExtension.cs
new file mode 100644
index 0000000000000000000000000000000000000000..ad7cff2ec4f587ac7ff83232112dfc073d0fa742
--- /dev/null
+++ b/Infrastructure/Extensions/ConvertJsonExtension.cs
@@ -0,0 +1,361 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Data;
+using System.Reflection;
+using System.Text;
+using Newtonsoft.Json;
+
+namespace Infrastructure.Extensions
+{
+ public static class ConvertJsonExtension
+ {
+ #region 私有方法
+ ///
+ /// 过滤特殊字符
+ ///
+ /// 字符串
+ /// json字符串
+ private static string String2Json(String s)
+ {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < s.Length; i++)
+ {
+ char c = s.ToCharArray()[i];
+ switch (c)
+ {
+ case '\"':
+ sb.Append("\\\""); break;
+ case '\\':
+ sb.Append("\\\\"); break;
+ case '/':
+ sb.Append("\\/"); break;
+ case '\b':
+ sb.Append("\\b"); break;
+ case '\f':
+ sb.Append("\\f"); break;
+ case '\n':
+ sb.Append("\\n"); break;
+ case '\r':
+ sb.Append("\\r"); break;
+ case '\t':
+ sb.Append("\\t"); break;
+ default:
+ sb.Append(c); break;
+ }
+ }
+ return sb.ToString();
+ }
+ ///
+ /// 格式化字符型、日期型、布尔型
+ ///
+ ///
+ ///
+ ///
+ private static string StringFormat(string str, Type type)
+ {
+ if (type == typeof(string))
+ {
+ str = String2Json(str);
+ str = "\"" + str + "\"";
+ }
+ else if (type == typeof(DateTime))
+ {
+ str = "\"" + str + "\"";
+ }
+ else if (type == typeof(bool))
+ {
+ str = str.ToLower();
+ }
+ else if (type != typeof(string) && string.IsNullOrEmpty(str))
+ {
+ str = "\"" + str + "\"";
+ }
+ return str;
+ }
+
+ #endregion
+
+ #region list转换成JSON
+ ///
+ /// list转换为Json
+ ///
+ ///
+ ///
+ ///
+ public static string ListToJson(this IList list)
+ {
+ object obj = list[0];
+ return ListToJson(list, obj.GetType().Name);
+ }
+ ///
+ /// list转换为json
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static string ListToJson(this IList list, string JsonName)
+ {
+ if (list.Count == 0)
+ {
+ return "";
+ }
+ StringBuilder Json = new StringBuilder();
+ if (string.IsNullOrEmpty(JsonName))
+ JsonName = list[0].GetType().Name;
+ Json.Append("{\"" + JsonName + "\":[");
+
+ for (int i = 0; i < list.Count; i++)
+ {
+ T obj = Activator.CreateInstance();
+ PropertyInfo[] pi = obj.GetType().GetProperties();
+ Json.Append("{");
+ for (int j = 0; j < pi.Length; j++)
+ {
+ Type type = pi[j].GetValue(list[i], null).GetType();
+ Json.Append("\"" + pi[j].Name.ToString() + "\":" + StringFormat(pi[j].GetValue(list[i], null).ToString(), type));
+ if (j < pi.Length - 1)
+ {
+ Json.Append(",");
+ }
+ }
+ Json.Append("}");
+ if (i < list.Count - 1)
+ {
+ Json.Append(",");
+ }
+ }
+ Json.Append("]}");
+ return Json.ToString();
+ }
+ #endregion
+
+ #region 对象转换为Json
+ ///
+ /// 对象转换为json
+ ///
+ /// json对象
+ /// json字符串
+ public static string ToJson(this object jsonObject)
+ {
+ string jsonString = "{";
+ PropertyInfo[] propertyInfo = jsonObject.GetType().GetProperties();
+ for (int i = 0; i < propertyInfo.Length; i++)
+ {
+ object objectValue = propertyInfo[i].GetGetMethod().Invoke(jsonObject, null);
+ string value = string.Empty;
+ if (objectValue is DateTime || objectValue is Guid || objectValue is TimeSpan)
+ {
+ value = "'" + objectValue.ToString() + "'";
+ }
+ else if (objectValue is string)
+ {
+ value = "'" + ToJson(objectValue.ToString()) + "'";
+ }
+ else if (objectValue is IEnumerable)
+ {
+ value = ToJson((IEnumerable)objectValue);
+ }
+ else
+ {
+ value = ToJson(objectValue.ToString());
+ }
+ jsonString += "\"" + ToJson(propertyInfo[i].Name) + "\":" + value + ",";
+ }
+ jsonString.Remove(jsonString.Length - 1, jsonString.Length);
+ return jsonString + "}";
+ }
+
+ #endregion
+
+ #region 对象集合转换为json
+ ///
+ /// 对象集合转换为json
+ ///
+ /// 对象集合
+ /// json字符串
+ public static string ToJson(this IEnumerable array)
+ {
+ string jsonString = "{";
+ foreach (object item in array)
+ {
+ jsonString += ToJson(item) + ",";
+ }
+ jsonString.Remove(jsonString.Length - 1, jsonString.Length);
+ return jsonString + "]";
+ }
+ #endregion
+
+ #region 普通集合转换Json
+ ///
+ /// 普通集合转换Json
+ ///
+ /// 集合对象
+ /// Json字符串
+ public static string ToArrayString(this IEnumerable array)
+ {
+ string jsonString = "[";
+ foreach (object item in array)
+ {
+ jsonString = ToJson(item.ToString()) + ",";
+ }
+ jsonString.Remove(jsonString.Length - 1, jsonString.Length);
+ return jsonString + "]";
+ }
+ #endregion
+
+ #region DataSet转换为Json
+ ///
+ /// DataSet转换为Json
+ ///
+ /// DataSet对象
+ /// Json字符串
+ public static string ToJson(this DataSet dataSet)
+ {
+ string jsonString = "{";
+ foreach (DataTable table in dataSet.Tables)
+ {
+ jsonString += "\"" + table.TableName + "\":" + ToJson(table) + ",";
+ }
+ jsonString = jsonString.TrimEnd(',');
+ return jsonString + "}";
+ }
+ #endregion
+
+ #region Datatable转换为Json
+ ///
+ /// Datatable转换为Json
+ ///
+ /// Datatable对象
+ /// Json字符串
+ public static string ToJson(this DataTable dt)
+ {
+ StringBuilder jsonString = new StringBuilder();
+ jsonString.Append("[");
+ DataRowCollection drc = dt.Rows;
+ for (int i = 0; i < drc.Count; i++)
+ {
+ jsonString.Append("{");
+ for (int j = 0; j < dt.Columns.Count; j++)
+ {
+ string strKey = dt.Columns[j].ColumnName;
+ string strValue = drc[i][j].ToString();
+ Type type = dt.Columns[j].DataType;
+ jsonString.Append("\"" + strKey + "\":");
+ strValue = StringFormat(strValue, type);
+ if (j < dt.Columns.Count - 1)
+ {
+ jsonString.Append(strValue + ",");
+ }
+ else
+ {
+ jsonString.Append(strValue);
+ }
+ }
+ jsonString.Append("},");
+ }
+ jsonString.Remove(jsonString.Length - 1, 1);
+ jsonString.Append("]");
+ return jsonString.ToString();
+ }
+ ///
+ /// DataTable转换为Json
+ ///
+ public static string ToJson(this DataTable dt, string jsonName)
+ {
+ StringBuilder Json = new StringBuilder();
+ if (string.IsNullOrEmpty(jsonName))
+ jsonName = dt.TableName;
+ Json.Append("{\"" + jsonName + "\":[");
+ if (dt.Rows.Count > 0)
+ {
+ for (int i = 0; i < dt.Rows.Count; i++)
+ {
+ Json.Append("{");
+ for (int j = 0; j < dt.Columns.Count; j++)
+ {
+ Type type = dt.Rows[i][j].GetType();
+ Json.Append("\"" + dt.Columns[j].ColumnName.ToString() + "\":" + StringFormat(dt.Rows[i][j].ToString(), type));
+ if (j < dt.Columns.Count - 1)
+ {
+ Json.Append(",");
+ }
+ }
+ Json.Append("}");
+ if (i < dt.Rows.Count - 1)
+ {
+ Json.Append(",");
+ }
+ }
+ }
+ Json.Append("]}");
+ return Json.ToString();
+ }
+
+ #endregion
+
+ #region DataReader转换为Json
+ ///
+ /// DataReader转换为Json
+ ///
+ /// DataReader对象
+ /// Json字符串
+ public static string ReaderJson(this IDataReader dataReader)
+ {
+ StringBuilder jsonString = new StringBuilder();
+ Dictionary ModelField = new Dictionary();
+ for (int i = 0; i < dataReader.FieldCount; i++)
+ {
+ ModelField.Add(dataReader.GetName(i), dataReader.GetFieldType(i));
+ }
+ jsonString.Append("[");
+ while (dataReader.Read())
+ {
+ jsonString.Append("{");
+ foreach (KeyValuePair keyVal in ModelField)
+ {
+ Type type = keyVal.Value;
+ string strKey = keyVal.Key;
+ string strValue = dataReader[strKey].ToString();
+ jsonString.Append("\"" + strKey + "\":");
+ strValue = StringFormat(strValue, type);
+ jsonString.Append(strValue + ",");
+ }
+ jsonString.Remove(jsonString.Length - 1, 1);
+ jsonString.Append("},");
+ }
+ dataReader.Close();
+ jsonString.Remove(jsonString.Length - 1, 1);
+ jsonString.Append("]");
+ return jsonString.ToString();
+ }
+ #endregion
+
+
+ public static T DeserializeObject(this string entityString)
+ {
+ if (string.IsNullOrEmpty(entityString))
+ {
+ return default(T);
+ }
+ if (entityString == "{}")
+ {
+ entityString = "[]";
+ }
+ return JsonConvert.DeserializeObject(entityString);
+ }
+
+ public static string Serialize(this object obj, JsonSerializerSettings formatDate = null)
+ {
+ if (obj == null) return null;
+ formatDate = formatDate ?? new JsonSerializerSettings
+ {
+ DateFormatString = "yyyy-MM-dd HH:mm:ss"
+ };
+ return JsonConvert.SerializeObject(obj, formatDate);
+ }
+
+ }
+}
+
diff --git a/Infrastructure/Extensions/DateTimeExtension.cs b/Infrastructure/Extensions/DateTimeExtension.cs
new file mode 100644
index 0000000000000000000000000000000000000000..bf3914a8ad86d6f99be901e55410886825bb0132
--- /dev/null
+++ b/Infrastructure/Extensions/DateTimeExtension.cs
@@ -0,0 +1,34 @@
+using System;
+
+namespace Infrastructure.Extensions
+{
+ public static class DateTimeExtension
+ {
+ ///
+ /// 实现由C# 的时间到 Javascript 的时间的转换
+ /// returns the number of milliseconds since Jan 1, 1970 (useful for converting C# dates to JS dates)
+ ///
+ ///
+ ///
+ public static double UnixTicks(this DateTime dt)
+ {
+ DateTime d1 = new DateTime(1970, 1, 1);
+ DateTime d2 = dt.AddHours(8).ToUniversalTime();
+ TimeSpan ts = new TimeSpan(d2.Ticks - d1.Ticks);
+ return ts.TotalMilliseconds;
+ }
+
+ ///
+ /// 将毫秒值转成 C# DateTime 类型
+ ///
+ ///
+ ///
+ public static DateTime ConvertTime(this long time)
+ {
+ DateTime timeStamp = new DateTime(1970, 1, 1); //得到1970年的时间戳
+ long t = (time + 8 * 60 * 60) * 10000000 + timeStamp.Ticks;
+ DateTime dt = new DateTime(t);
+ return dt;
+ }
+ }
+}
diff --git a/Infrastructure/Extensions/EntityProperties.cs b/Infrastructure/Extensions/EntityProperties.cs
new file mode 100644
index 0000000000000000000000000000000000000000..72f7619ef160be488c271aee6c87b149adc8520c
--- /dev/null
+++ b/Infrastructure/Extensions/EntityProperties.cs
@@ -0,0 +1,1219 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Data;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Text;
+using Infrastructure.Const;
+using Infrastructure.Utilities;
+
+namespace Infrastructure.Extensions
+{
+ public static class EntityProperties
+ {
+
+ public static string GetExpressionPropertyFirst(this Expression> properties)
+ {
+ string[] arr = properties.GetExpressionProperty();
+ if (arr.Length > 0)
+ return arr[0];
+ return "";
+ }
+ ///
+ /// 获取对象里指定成员名称
+ ///
+ ///
+ /// 格式 Expression> exp = x => new { x.字段1, x.字段2 };或x=>x.Name
+ ///
+ public static string[] GetExpressionProperty(this Expression> properties)
+ {
+ if (properties == null)
+ return new string[] { };
+ if (properties.Body is NewExpression)
+ return ((NewExpression)properties.Body).Members.Select(x => x.Name).ToArray();
+ if (properties.Body is MemberExpression)
+ return new string[] { ((MemberExpression)properties.Body).Member.Name };
+ if (properties.Body is UnaryExpression)
+ return new string[] { ((properties.Body as UnaryExpression).Operand as MemberExpression).Member.Name };
+ throw new Exception("未实现的表达式");
+ }
+ public static string ValidateHashInEntity(this Type typeinfo, Dictionary dic)
+ {
+ return typeinfo.ValidateDicInEntity(dic, false);
+ }
+
+ public static void RemoveNotExistColumns(this Type typeinfo, List cols)
+ {
+
+ }
+
+ ///
+ /// 获取所有字段的名称
+ ///
+ ///
+ ///
+ public static List GetAtrrNames(this Type typeinfo)
+ {
+ return typeinfo.GetProperties().Select(c => c.Name).ToList();
+ }
+ public static void IsExistColumns(this Type typeinfo)
+ {
+
+ }
+ public static Dictionary GetColumType(this PropertyInfo[] properties)
+ {
+ return properties.GetColumType(false);
+ }
+ public static Dictionary GetColumType(this PropertyInfo[] properties, bool containsKey)
+ {
+ Dictionary dictionary = new Dictionary();
+ foreach (PropertyInfo property in properties)
+ {
+ if (!containsKey && property.IsKey())
+ {
+ continue;
+ }
+ var keyVal = GetColumnType(property, true);
+ dictionary.Add(keyVal.Key, keyVal.Value);
+ }
+ return dictionary;
+ }
+
+ private static readonly Dictionary entityMapDbColumnType = new Dictionary() {
+ {typeof(int),SqlDbTypeName.Int },
+ {typeof(int?),SqlDbTypeName.Int },
+ {typeof(long),SqlDbTypeName.BigInt },
+ {typeof(long?),SqlDbTypeName.BigInt },
+ {typeof(decimal),"decimal(18, 5)" },
+ {typeof(decimal?),"decimal(18, 5)" },
+ {typeof(double),"decimal(18, 5)" },
+ {typeof(double?),"decimal(18, 5)" },
+ {typeof(float),"decimal(18, 5)" },
+ {typeof(float?),"decimal(18, 5)" },
+ {typeof(Guid),"UniqueIdentifier" },
+ {typeof(Guid?),"UniqueIdentifier" },
+ {typeof(byte),"tinyint" },
+ {typeof(byte?),"tinyint" },
+ {typeof(string),"nvarchar" }
+ };
+ ///
+ /// 返回属性的字段及数据库类型
+ ///
+ ///
+ /// 是否包括后字段具体长度:nvarchar(100)
+ ///
+ public static KeyValuePair GetColumnType(this PropertyInfo property, bool lenght = false)
+ {
+ string colType = "";
+ object objAtrr = property.GetTypeCustomAttributes(typeof(ColumnAttribute), out bool asType);
+ if (asType)
+ {
+ colType = ((ColumnAttribute)objAtrr).TypeName.ToLower();
+ if (!string.IsNullOrEmpty(colType))
+ {
+ //不需要具体长度直接返回
+ if (!lenght)
+ {
+ return new KeyValuePair(property.Name, colType);
+ }
+ if (colType == "decimal" || colType == "double" || colType == "float")
+ {
+ objAtrr = property.GetTypeCustomAttributes(typeof(DisplayFormatAttribute), out asType);
+ colType += "(" + (asType ? ((DisplayFormatAttribute)objAtrr).DataFormatString : "18,5") + ")";
+
+ }
+ ///如果是string,根据 varchar或nvarchar判断最大长度
+ if (property.PropertyType.ToString() == "System.String")
+ {
+ colType = colType.Split("(")[0];
+ objAtrr = property.GetTypeCustomAttributes(typeof(MaxLengthAttribute), out asType);
+ if (asType)
+ {
+ int length = ((MaxLengthAttribute)objAtrr).Length;
+ colType += "(" + (length < 1 || length > (colType.StartsWith("n") ? 8000 : 4000) ? "max" : length.ToString()) + ")";
+ }
+ else
+ {
+ colType += "(max)";
+ }
+ }
+ return new KeyValuePair(property.Name, colType);
+ }
+ }
+ if (entityMapDbColumnType.TryGetValue(property.PropertyType, out string value))
+ {
+ colType = value;
+ }
+ else
+ {
+ colType = SqlDbTypeName.NVarChar;
+ }
+ if (lenght && colType == SqlDbTypeName.NVarChar)
+ {
+ colType = "nvarchar(max)";
+ }
+ return new KeyValuePair(property.Name, colType);
+ }
+
+ ///
+ ///
+ ///
+ /// 将数组转换成sql语句
+ /// 指定FieldType数据库字段类型
+ ///
+ ///
+ public static string GetArraySql(this object[] array, FieldType fieldType)
+ {
+ if (array == null || array.Count() == 0)
+ {
+ return string.Empty;
+ }
+ string columnType = string.Empty;
+ List arrrayEntityList = array.Select(x => new ArrayEntity { column1 = x.ToString() }).ToList();
+ return arrrayEntityList.GetEntitySql(false, null, null, null, fieldType);
+ }
+ ///
+ ///要执行的sql语句如:通过EntityToSqlTempName.Temp_Insert0.ToString()字符串占位,生成的的sql语句会把EntityToSqlTempName.Temp_Insert0.ToString()替换成生成的sql临时表数据
+ /// string sql = " ;DELETE FROM " + typeEntity.Name + " where " + typeEntity.GetKeyName() +
+ /// " in (select * from " + EntityToSqlTempName.Temp_Insert0.ToString() + ")";
+ ///
+ ///
+ ///
+ /// 指定生成的数组值的类型
+ ///
+ ///
+ public static string GetArraySql(this object[] array, FieldType fieldType, string sql)
+ {
+ if (array == null || array.Count() == 0)
+ {
+ return string.Empty;
+ }
+ string columnType = string.Empty;
+ List arrrayEntityList = array.Select(x => new ArrayEntity { column1 = x.ToString() }).ToList();
+ return arrrayEntityList.GetEntitySql(false, sql, null, null, fieldType);
+ }
+ public static string GetArraySql(this object[] array, string sql)
+ {
+ return array.GetArraySql(typeof(T).GetFieldType(), sql);
+ }
+ ///
+ /// 根据实体获取key的类型,用于update或del操作
+ ///
+ ///
+ ///
+ public static FieldType GetFieldType(this Type typeEntity)
+ {
+ FieldType fieldType;
+ string columnType = typeEntity.GetProperties().Where(x => x.Name == typeEntity.GetKeyName()).ToList()[0].GetColumnType(false).Value;
+ switch (columnType)
+ {
+ case SqlDbTypeName.Int: fieldType = FieldType.Int; break;
+ case SqlDbTypeName.BigInt: fieldType = FieldType.BigInt; break;
+ case SqlDbTypeName.VarChar: fieldType = FieldType.VarChar; break;
+ case SqlDbTypeName.UniqueIdentifier: fieldType = FieldType.UniqueIdentifier; break;
+ default: fieldType = FieldType.NvarChar; break;
+ }
+ return fieldType;
+ }
+ public static string GetEntitySql(this IEnumerable entityList,
+ bool containsKey = false,
+ string sql = null,
+ Expression> ignoreFileds = null,
+ Expression> fixedColumns = null,
+ FieldType? fieldType = null
+ )
+ {
+
+ if (entityList == null || entityList.Count() == 0) return "";
+ PropertyInfo[] propertyInfo = typeof(T).GetProperties().ToArray();
+ if (propertyInfo.Count() == 0)
+ {
+ propertyInfo = entityList.ToArray()[0].GetType().GetGenericProperties().ToArray();
+ }
+ propertyInfo = propertyInfo.GetGenericProperties().ToArray();
+
+ string[] arr = null;
+ if (fixedColumns != null)
+ {
+ arr = fixedColumns.GetExpressionToArray();
+ PropertyInfo keyProperty = typeof(T).GetKeyProperty();
+ propertyInfo = propertyInfo.Where(x => (containsKey && x.Name == keyProperty.Name) || arr.Contains(x.Name)).ToArray();
+ }
+ if (ignoreFileds != null)
+ {
+ arr = ignoreFileds.GetExpressionToArray();
+ propertyInfo = propertyInfo.Where(x => !arr.Contains(x.Name)).ToArray();
+ }
+
+ Dictionary dictProperties = propertyInfo.GetColumType(containsKey);
+ if (fieldType != null)
+ {
+ string realType = fieldType.ToString();
+ if ((int)fieldType == 0 || (int)fieldType == 1)
+ {
+ realType += "(max)";
+ }
+ dictProperties = new Dictionary { { dictProperties.Select(x => x.Key).ToList()[0], realType } };
+ }
+ if (dictProperties.Keys.Count * entityList.Count() > 50 * 3000)
+ {
+ throw new Exception("写入数据太多,请分开写入。");
+ }
+
+ string cols = string.Join(",", dictProperties.Select(c => "[" + c.Key + "]" + " " + c.Value));
+ StringBuilder declareTable = new StringBuilder();
+
+ string tempTablbe = "#" + EntityToSqlTempName.TempInsert.ToString();
+
+ declareTable.Append("CREATE TABLE " + tempTablbe + " (" + cols + ")");
+ declareTable.Append("\r\n");
+
+ //参数总数量
+ int parCount = (dictProperties.Count) * (entityList.Count());
+ int takeCount = 0;
+ int maxParsCount = 2050;
+ if (parCount > maxParsCount)
+ {
+ //如果参数总数量超过2100,设置每次分批循环写入表的大小
+ takeCount = maxParsCount / dictProperties.Count;
+ }
+
+ int count = 0;
+ StringBuilder stringLeft = new StringBuilder();
+ StringBuilder stringCenter = new StringBuilder();
+ StringBuilder stringRight = new StringBuilder();
+
+ int index = 0;
+ foreach (T entity in entityList)
+ {
+ //每1000行需要分批写入(数据库限制每批至多写入1000行数据)
+ if (index == 0 || index >= 1000 || takeCount - index == 0)
+ {
+ if (stringLeft.Length > 0)
+ {
+ declareTable.AppendLine(
+ stringLeft.Remove(stringLeft.Length - 2, 2).Append("',").ToString() +
+ stringCenter.Remove(stringCenter.Length - 1, 1).Append("',").ToString() +
+ stringRight.Remove(stringRight.Length - 1, 1).ToString());
+
+ stringLeft.Clear(); stringCenter.Clear(); stringRight.Clear();
+ }
+
+ stringLeft.AppendLine("exec sp_executesql N'SET NOCOUNT ON;");
+ stringCenter.Append("N'");
+
+ index = 0; count = 0;
+ }
+ stringLeft.Append(index == 0 ? "; INSERT INTO " + tempTablbe + " values (" : " ");
+ index++;
+ foreach (PropertyInfo property in propertyInfo)
+ {
+ if (!containsKey && property.IsKey()) { continue; }
+ string par = "@v" + count;
+ stringLeft.Append(par + ",");
+ stringCenter.Append(par + " " + dictProperties[property.Name] + ",");
+ object val = property.GetValue(entity);
+ if (val == null)
+ {
+ stringRight.Append(par + "=NUll,");
+ }
+ else
+ {
+ stringRight.Append(par + "='" + val.ToString().Replace("'", "''''") + "',");
+ }
+ count++;
+ }
+ stringLeft.Remove(stringLeft.Length - 1, 1);
+ stringLeft.Append("),(");
+ }
+
+ if (stringLeft.Length > 0)
+ {
+ declareTable.AppendLine(
+ stringLeft.Remove(stringLeft.Length - 2, 2).Append("',").ToString() +
+ stringCenter.Remove(stringCenter.Length - 1, 1).Append("',").ToString() +
+ stringRight.Remove(stringRight.Length - 1, 1).ToString());
+
+ stringLeft.Clear(); stringCenter.Clear(); stringRight.Clear();
+ }
+ if (!string.IsNullOrEmpty(sql))
+ {
+ sql = sql.Replace(EntityToSqlTempName.TempInsert.ToString(), tempTablbe);
+ declareTable.AppendLine(sql);
+ }
+ else
+ {
+ declareTable.AppendLine(" SELECT " + (string.Join(",", fixedColumns?.GetExpressionToArray() ?? new string[] { "*" })) + " FROM " + tempTablbe);
+ }
+
+
+ if (tempTablbe.Substring(0, 1) == "#")
+ {
+ declareTable.AppendLine("; drop table " + tempTablbe);
+ }
+ return declareTable.ToString();
+ }
+
+
+ ///
+ ///此方法适用于数据量少,只有几列数据,不超过1W行,或几十列数据不超过1000行的情况下使用
+ /// 大批量的数据考虑其他方式
+ /// 將datatable生成sql語句,替換datatable作為參數傳入存儲過程
+ ///
+ ///
+ ///
+ public static string GetDataTableSql(this DataTable table)
+ {
+ Dictionary dictCloumn = new Dictionary();
+ for (int i = 0; i < table.Columns.Count; i++)
+ {
+ dictCloumn.Add(table.Columns[i].ColumnName, " nvarchar(max)");
+ }
+
+
+ //参数总数量
+ int parCount = (dictCloumn.Count) * (table.Rows.Count);
+ int takeCount = 0;
+ int maxParsCount = 2050;
+ if (parCount > maxParsCount)
+ {
+ //如果参数总数量超过2100,设置每次分批循环写入表的大小
+ takeCount = maxParsCount / dictCloumn.Count;
+ }
+
+ if (dictCloumn.Keys.Count * table.Rows.Count > 50 * 3000)
+ {
+ throw new Exception("写入数据太多,请分开写入。");
+ }
+
+ string cols = string.Join(",", dictCloumn.Select(c => "[" + c.Key + "]" + " " + c.Value));
+ StringBuilder declareTable = new StringBuilder();
+
+ string tempTablbe = "#Temp_Insert0";
+ declareTable.Append("CREATE TABLE " + tempTablbe + " (" + cols + ")");
+ declareTable.Append("\r\n");
+ int count = 0;
+ StringBuilder stringLeft = new StringBuilder();
+ StringBuilder stringCenter = new StringBuilder();
+ StringBuilder stringRight = new StringBuilder();
+
+ int index = 0;
+
+ foreach (DataRow row in table.Rows)
+ {
+ //每1000行需要分批写入(数据库限制每批至多写入1000行数据)
+ if (index == 0 || index >= 1000 || takeCount - index == 0)
+ {
+ if (stringLeft.Length > 0)
+ {
+ declareTable.AppendLine(
+ stringLeft.Remove(stringLeft.Length - 2, 2).Append("',").ToString() +
+ stringCenter.Remove(stringCenter.Length - 1, 1).Append("',").ToString() +
+ stringRight.Remove(stringRight.Length - 1, 1).ToString());
+
+ stringLeft.Clear(); stringCenter.Clear(); stringRight.Clear();
+ }
+ // sbLeft.AppendLine(" INSERT INTO @toInsert0");
+ stringLeft.AppendLine("exec sp_executesql N'SET NOCOUNT ON;");
+ stringCenter.Append("N'");
+
+ index = 0; count = 0;
+ }
+ stringLeft.Append(index == 0 ? "; INSERT INTO " + tempTablbe + " values (" : " ");
+ index++;
+ foreach (KeyValuePair keyValue in dictCloumn)
+ {
+ string par = "@v" + count;
+ stringLeft.Append(par + ",");
+ stringCenter.Append(par + " " + keyValue.Value + ",");
+ object val = row[keyValue.Key];
+ if (val == null)
+ {
+ stringRight.Append(par + "=NUll,");
+ }
+ else
+ {
+ stringRight.Append(par + "='" + val.ToString().Replace("'", "''''") + "',");
+ }
+ count++;
+ }
+ stringLeft.Remove(stringLeft.Length - 1, 1);
+ stringLeft.Append("),(");
+ }
+
+
+
+
+ if (stringLeft.Length > 0)
+ {
+
+ declareTable.AppendLine(
+ stringLeft.Remove(stringLeft.Length - 2, 2).Append("',").ToString() +
+ stringCenter.Remove(stringCenter.Length - 1, 1).Append("',").ToString() +
+ stringRight.Remove(stringRight.Length - 1, 1).ToString());
+
+ stringLeft.Clear(); stringCenter.Clear(); stringRight.Clear();
+ }
+ declareTable.AppendLine(" SELECT * FROM " + tempTablbe);
+ if (tempTablbe.Substring(0, 1) == "#")
+ {
+ declareTable.AppendLine("; drop table " + tempTablbe);
+ }
+ return declareTable.ToString();
+ }
+
+
+
+ public static string GetKeyName(this Type typeinfo)
+ {
+ return typeinfo.GetProperties().GetKeyName();
+ }
+ public static string GetKeyType(this Type typeinfo)
+ {
+ string keyType = typeinfo.GetProperties().GetKeyName(true);
+ if (keyType == "varchar")
+ {
+ return "varchar(max)";
+ }
+ else if (keyType != "nvarchar")
+ {
+ return keyType;
+ }
+ else
+ {
+ return "nvarchar(max)";
+ }
+ }
+ public static string GetKeyName(this PropertyInfo[] properties)
+ {
+ return properties.GetKeyName(false);
+ }
+ ///
+ /// 获取key列名
+ ///
+ ///
+ /// true获取key对应类型,false返回对象Key的名称
+ ///
+ public static string GetKeyName(this PropertyInfo[] properties, bool keyType)
+ {
+ string keyName = string.Empty;
+ foreach (PropertyInfo propertyInfo in properties)
+ {
+ if (!propertyInfo.IsKey())
+ continue;
+ if (!keyType)
+ return propertyInfo.Name;
+ var attributes = propertyInfo.GetCustomAttributes(typeof(ColumnAttribute), false);
+ //如果没有ColumnAttribute的需要单独再验证,下面只验证有属性的
+ if (attributes.Length > 0)
+ return ((ColumnAttribute)attributes[0]).TypeName.ToLower();
+ else
+ return GetColumType(new PropertyInfo[] { propertyInfo }, true)[propertyInfo.Name];
+ }
+ return keyName;
+ }
+
+ ///
+ /// 获取主键字段
+ ///
+ ///
+ ///
+ public static PropertyInfo GetKeyProperty(this Type entity)
+ {
+ return entity.GetProperties().GetKeyProperty();
+ }
+ public static PropertyInfo GetKeyProperty(this PropertyInfo[] properties)
+ {
+ return properties.Where(c => c.IsKey()).FirstOrDefault();
+ }
+ public static bool IsKey(this PropertyInfo propertyInfo)
+ {
+ object[] keyAttributes = propertyInfo.GetCustomAttributes(typeof(KeyAttribute), false);
+ if (keyAttributes.Length > 0)
+ return true;
+ return false;
+ }
+
+
+ private static string[] _userEditFields { get; set; }
+
+
+
+
+ ///
+ /// 判断是否包含某个属性:
+ /// 如 [Editable(true)]
+ // public string MO { get; set; }包含Editable
+ ///
+ ///
+ ///
+ ///
+ public static bool ContainsCustomAttributes(this PropertyInfo propertyInfo, Type type)
+ {
+ propertyInfo.GetTypeCustomAttributes(type, out bool contains);
+ return contains;
+ }
+
+ public static List ContainsCustomAttributes(this Type obj, Type containType)
+ {
+ List proList = new List();
+ foreach (PropertyInfo pro in obj.GetProperties())
+ {
+ if (pro.GetTypeCustomAttributes(containType) != null)
+ {
+ proList.Add(pro);
+ }
+ }
+ return proList;
+ }
+
+ ///
+ /// 获取PropertyInfo指定属性
+ ///
+ ///
+ ///
+ ///
+ public static object GetTypeCustomAttributes(this PropertyInfo propertyInfo, Type type, out bool asType)
+ {
+ object[] attributes = propertyInfo.GetCustomAttributes(type, false);
+ if (attributes.Length == 0)
+ {
+ asType = false;
+ return new string[0];
+ }
+ asType = true;
+ return attributes[0];
+ }
+
+ ///
+ /// 验证集合的属性
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static WebResponseContent ValidationEntityList(this List entityList, Expression> expression = null)
+ {
+ WebResponseContent responseData = new WebResponseContent();
+ foreach (T entity in entityList)
+ {
+ responseData = entity.ValidationEntity(expression);
+ if (!responseData.Status)
+ {
+ return responseData;
+ }
+ }
+ responseData.Status = true;
+ return responseData;
+ }
+ ///
+ /// 指定需要验证的字段
+ ///
+ ///
+ ///
+ /// 对指定属性进行验证x=>{x.Name,x.Size}
+ ///
+ public static WebResponseContent ValidationEntity(this T entity, Expression> expression = null, Expression> validateProperties = null)
+ {
+ return ValidationEntity(entity, expression?.GetExpressionProperty(), validateProperties?.GetExpressionProperty());
+ }
+ ///
+ /// specificProperties=null并且validateProperties=null,对所有属性验证,只验证其是否合法,不验证是否为空(除属性标识指定了不能为空外)
+ /// specificProperties!=null,对指定属性校验,并且都必须有值
+ /// null并且validateProperties!=null,对指定属性校验,不判断是否有值
+ ///
+ ///
+ ///
+ /// 验证指定的属性,并且非空判断
+ /// 验证指定属性,只对字段合法性判断,不验证是否为空
+ ///
+ public static WebResponseContent ValidationEntity(this T entity, string[] specificProperties, string[] validateProperties = null)
+ {
+ WebResponseContent responseData = new WebResponseContent();
+ if (entity == null) return responseData.Error("对象不能为null");
+
+ PropertyInfo[] propertyArray = typeof(T).GetProperties();
+ //若T为object取不到属性
+ if (propertyArray.Length == 0)
+ {
+ propertyArray = entity.GetType().GetProperties();
+ }
+ List compareProper = new List();
+
+ //只验证数据合法性,验证非空
+ if (specificProperties != null && specificProperties.Length > 0)
+ {
+ compareProper.AddRange(propertyArray.Where(x => specificProperties.Contains(x.Name)));
+ }
+
+ //只验证数据合法性,不验证非空
+ if (validateProperties != null && validateProperties.Length > 0)
+ {
+ compareProper.AddRange(propertyArray.Where(x => validateProperties.Contains(x.Name)));
+ }
+ if (compareProper.Count() > 0)
+ {
+ propertyArray = compareProper.ToArray();
+ }
+ foreach (PropertyInfo propertyInfo in propertyArray)
+ {
+ object value = propertyInfo.GetValue(entity);
+ //设置默认状态的值
+ if (propertyInfo.Name == "Enable" || propertyInfo.Name == "AuditStatus")
+ {
+ if (value == null)
+ {
+ propertyInfo.SetValue(entity, 0);
+ continue;
+ }
+ }
+ //若存在specificProperties并且属性为数组specificProperties中的值,校验时就需要判断是否为空
+ var reslut = propertyInfo.ValidationProperty(value,
+ specificProperties != null && specificProperties.Contains(propertyInfo.Name) ? true : false
+ );
+ if (!reslut.Item1)
+ return responseData.Error(reslut.Item2);
+ }
+ return responseData.OK();
+ }
+
+ ///
+ /// 获取数据库类型,不带长度,如varchar(100),只返回的varchar
+ ///
+ ///
+ ///
+ public static string GetSqlDbType(this PropertyInfo propertyInfo)
+ {
+ string dbType = propertyInfo.GetTypeCustomValue(x => new { x.TypeName });
+
+ if (string.IsNullOrEmpty(dbType))
+ {
+ return dbType;
+ }
+ dbType = dbType.ToLower();
+ if (dbType.Contains(SqlDbTypeName.NVarChar))
+ {
+ dbType = SqlDbTypeName.NVarChar;
+ }
+ else if (dbType.Contains(SqlDbTypeName.VarChar))
+ {
+ dbType = SqlDbTypeName.VarChar;
+ }
+ else if (dbType.Contains(SqlDbTypeName.NChar))
+ {
+ dbType = SqlDbTypeName.NChar;
+ }
+ else if (dbType.Contains(SqlDbTypeName.Char))
+ {
+ dbType = SqlDbTypeName.Char;
+ }
+
+ return dbType;
+ }
+
+ ///
+ /// 验证数据库字段类型与值是否正确,
+ ///
+ /// propertyInfo为当字段,当前字段必须有ColumnAttribute属性,
+ /// 如字段:标识为数据库int类型[Column(TypeName="int")] public int Id { get; set; }
+ /// 如果是小数float或Decimal必须对propertyInfo字段加DisplayFormatAttribute属性
+ ///
+ ///
+ /// IEnumerable<(bool, string, object)> bool成否校验成功,string校验失败信息,object,当前校验的值
+ public static IEnumerable<(bool, string, object)> ValidationValueForDbType(this PropertyInfo propertyInfo, params object[] values)
+ {
+ string dbTypeName = propertyInfo.GetTypeCustomValue(c => c.TypeName);
+ foreach (object value in values)
+ {
+ yield return dbTypeName.ValidationVal(value, propertyInfo);
+ }
+ }
+
+ public static bool ValidationRquiredValueForDbType(this PropertyInfo propertyInfo, object value, out string message)
+ {
+ if (value == null || value?.ToString()?.Trim() == "")
+ {
+ message = $"{propertyInfo.GetDisplayName()}不能为空";
+ return false;
+ }
+ var result = propertyInfo.GetProperWithDbType().ValidationVal(value, propertyInfo);
+ message = result.Item2;
+ return result.Item1;
+ }
+
+ private static readonly Dictionary ProperWithDbType = new Dictionary() {
+ { typeof(string),SqlDbTypeName.NVarChar },
+ { typeof(DateTime),SqlDbTypeName.DateTime},
+ {typeof(long),SqlDbTypeName.BigInt },
+ {typeof(int),SqlDbTypeName.Int},
+ { typeof(decimal),SqlDbTypeName.Decimal },
+ { typeof(float),SqlDbTypeName.Float },
+ { typeof(double),SqlDbTypeName.Double },
+ { typeof(byte),SqlDbTypeName.Int },//类型待完
+ { typeof(Guid),SqlDbTypeName.UniqueIdentifier}
+ };
+ public static string GetProperWithDbType(this PropertyInfo propertyInfo)
+ {
+ bool result = ProperWithDbType.TryGetValue(propertyInfo.PropertyType, out string value);
+ if (result)
+ {
+ return value;
+ }
+ return SqlDbTypeName.NVarChar;
+ }
+
+ ///
+ /// 验证数据库字段类型与值是否正确,
+ ///
+ /// 数据库字段类型(如varchar,nvarchar,decimal,不要带后面长度如:varchar(50))
+ /// 值
+ /// 要验证的类的属性,若不为null,则会判断字符串的长度是否正确
+ /// (bool, string, object)bool成否校验成功,string校验失败信息,object,当前校验的值
+ public static (bool, string, object) ValidationVal(this string dbType, object value, PropertyInfo propertyInfo = null)
+ {
+ if (string.IsNullOrEmpty(dbType))
+ {
+ dbType = propertyInfo != null ? propertyInfo.GetProperWithDbType() : SqlDbTypeName.NVarChar;
+ }
+ dbType = dbType.ToLower();
+ string val = value?.ToString();
+ //验证长度
+ string reslutMsg = string.Empty;
+ if (dbType == SqlDbTypeName.Int || dbType == SqlDbTypeName.BigInt)
+ {
+ if (!StringExtension.IsInt(value))
+ reslutMsg = "只能为有效整数";
+ }
+ else if (dbType == SqlDbTypeName.DateTime
+ || dbType == SqlDbTypeName.Date
+ || dbType == SqlDbTypeName.SmallDateTime
+ || dbType == SqlDbTypeName.SmallDate
+ )
+ {
+ if (!StringExtension.IsDate(value))
+ reslutMsg = "必须为日期格式";
+ }
+ else if (dbType == SqlDbTypeName.Float || dbType == SqlDbTypeName.Decimal || dbType == SqlDbTypeName.Double)
+ {
+ string formatString = string.Empty;
+ if (propertyInfo != null)
+ formatString = propertyInfo.GetTypeCustomValue(x => x.DataFormatString);
+ //if (string.IsNullOrEmpty(formatString))
+ // throw new Exception("请对字段" + propertyInfo?.Name + "添加DisplayFormat属性标识");
+
+ if (!StringExtension.IsNumber(val, formatString))
+ {
+ string[] arr = (formatString ?? "10,0").Split(',');
+ reslutMsg = $"整数{arr[0]}最多位,小数最多{arr[1]}位";
+ }
+ }
+ else if (dbType == SqlDbTypeName.UniqueIdentifier)
+ {
+ if (!StringExtension.IsGuid(val))
+ {
+ reslutMsg = propertyInfo.Name + "Guid不正确";
+ }
+ }
+ else if (propertyInfo != null
+ && (dbType == SqlDbTypeName.VarChar
+ || dbType == SqlDbTypeName.NVarChar
+ || dbType == SqlDbTypeName.NChar
+ || dbType == SqlDbTypeName.Char
+ || dbType == SqlDbTypeName.Text))
+ {
+
+ //默认nvarchar(max) 、text 长度不能超过20000
+ if (val.Length > 20000)
+ {
+ reslutMsg = $"字符长度最多【20000】";
+ }
+ else
+ {
+ int length = StringExtension.GetInt(propertyInfo.GetTypeCustomValue(x => new { x.Length }));
+ if (length == 0) { return (true, null, null); }
+ //判断双字节与单字段
+ else if (length < 8000 &&
+ ((dbType.Substring(0, 1) != "n"
+ && Encoding.UTF8.GetBytes(val.ToCharArray()).Length > length)
+ || val.Length > length)
+ )
+ {
+ reslutMsg = $"最多只能【{length}】个字符。";
+ }
+ }
+ }
+ if (!string.IsNullOrEmpty(reslutMsg) && propertyInfo != null)
+ {
+ reslutMsg = propertyInfo.GetDisplayName() + reslutMsg;
+ }
+ return (reslutMsg == "" ? true : false, reslutMsg, value);
+ }
+
+ public static string GetDisplayName(this PropertyInfo property)
+ {
+ string displayName = property.GetTypeCustomValue(x => new { x.Name });
+ if (string.IsNullOrEmpty(displayName))
+ {
+ return property.Name;
+ }
+ return displayName;
+ }
+
+ ///
+ /// 验证每个属性的值是否正确
+ ///
+ ///
+ /// 属性的值
+ /// 是否指定当前属性必须有值
+ ///
+ public static (bool, string, object) ValidationProperty(this PropertyInfo propertyInfo, object objectVal, bool required)
+ {
+ if (propertyInfo.IsKey()) { return (true, null, objectVal); }
+
+ string val = objectVal == null ? "" : objectVal.ToString().Trim();
+
+ string requiredMsg = string.Empty;
+ if (!required)
+ {
+ var reuireVal = propertyInfo.GetTypeCustomValues(x => new { x.AllowEmptyStrings, x.ErrorMessage });
+ if (reuireVal != null && !Convert.ToBoolean(reuireVal["AllowEmptyStrings"]))
+ {
+ required = true;
+ requiredMsg = reuireVal["ErrorMessage"];
+ }
+ }
+ //如果不要求为必填项并且值为空,直接返回
+ if (!required && string.IsNullOrEmpty(val))
+ return (true, null, objectVal);
+
+ if ((required && val == string.Empty))
+ {
+ if (requiredMsg != "") return (false, requiredMsg, objectVal);
+ string propertyName = propertyInfo.GetTypeCustomValue(x => new { x.Name });
+ return (false, requiredMsg + (string.IsNullOrEmpty(propertyName) ? propertyInfo.Name : propertyName) + "不能为空", objectVal);
+ }
+ //列名
+ string typeName = propertyInfo.GetSqlDbType();
+
+ //如果没有ColumnAttribute的需要单独再验证,下面只验证有属性的
+ if (typeName == null) { return (true, null, objectVal); }
+ //验证长度
+ return typeName.ValidationVal(val, propertyInfo);
+ }
+ ///
+ /// 获取属性的指定属性
+ ///
+ ///
+ ///
+ ///
+ public static object GetTypeCustomAttributes(this MemberInfo member, Type type)
+ {
+ object[] obj = member.GetCustomAttributes(type, false);
+ if (obj.Length == 0) return null;
+ return obj[0];
+ }
+
+ ///
+ /// 获取类的指定属性
+ ///
+ ///
+ ///
+ ///
+ public static object GetTypeCustomAttributes(this Type entity, Type type)
+ {
+ object[] obj = entity.GetCustomAttributes(type, false);
+ if (obj.Length == 0) return null;
+ return obj[0];
+ }
+ ///
+ /// 获取类的多个指定属性的值
+ ///
+ /// 当前类
+ /// 指定的类
+ /// 指定属性的值 格式 Expression> exp = x => new { x.字段1, x.字段2 };
+ /// 返回的是字段+value
+ public static Dictionary GetTypeCustomValues(this MemberInfo member, Expression> expression)
+ {
+ var attr = member.GetTypeCustomAttributes(typeof(TEntity));
+ if (attr == null)
+ {
+ return null;
+ }
+
+ string[] propertyName = expression.GetExpressionProperty();
+ Dictionary propertyKeyValues = new Dictionary();
+
+ foreach (PropertyInfo property in attr.GetType().GetProperties())
+ {
+ if (propertyName.Contains(property.Name))
+ {
+ propertyKeyValues[property.Name] = (property.GetValue(attr) ?? string.Empty).ToString();
+ }
+ }
+ return propertyKeyValues;
+ }
+
+ ///
+ /// 获取类的单个指定属性的值(只会返回第一个属性的值)
+ ///
+ /// 当前类
+ /// 指定的类
+ /// 指定属性的值 格式 Expression> exp = x => new { x.字段1, x.字段2 };
+ ///
+ public static string GetTypeCustomValue(this MemberInfo member, Expression> expression)
+ {
+ var propertyKeyValues = member.GetTypeCustomValues(expression);
+ if (propertyKeyValues == null || propertyKeyValues.Count == 0)
+ {
+ return null;
+ }
+ return propertyKeyValues.First().Value ?? "";
+ }
+ ///
+ /// 判断hash的列是否为对应的实体,并且值是否有效
+ ///
+ ///
+ ///
+ /// 移除不存在字段
+ ///
+ public static string ValidateDicInEntity(this Type typeinfo, Dictionary dic, bool removeNotContains, string[] ignoreFields = null)
+ {
+ return typeinfo.ValidateDicInEntity(dic, removeNotContains, true, ignoreFields);
+ }
+
+ public static string ValidateDicInEntity(this Type type, List> dicList, bool removeNotContains, bool removerKey, string[] ignoreFields = null)
+ {
+ PropertyInfo[] propertyInfo = type.GetProperties();
+ string reslutMsg = string.Empty;
+ foreach (Dictionary dic in dicList)
+ {
+ reslutMsg = type.ValidateDicInEntity(dic, propertyInfo, removeNotContains, removerKey, ignoreFields);
+ if (!string.IsNullOrEmpty(reslutMsg))
+ return reslutMsg;
+ }
+ return reslutMsg;
+ }
+ public static string ValidateDicInEntity(this Type type, Dictionary dic, bool removeNotContains, bool removerKey, string[] ignoreFields = null)
+ {
+ return type.ValidateDicInEntity(dic, null, removeNotContains, removerKey, ignoreFields);
+ }
+ ///
+ /// 判断hash的列是否为对应的实体,并且值是否有效
+ ///
+ ///
+ ///
+ /// 移除不存在字段
+ /// 移除主键
+ ///
+ private static string ValidateDicInEntity(this Type typeinfo, Dictionary dic, PropertyInfo[] propertyInfo, bool removeNotContains, bool removerKey, string[] ignoreFields = null)
+ {
+ if (dic == null || dic.Count == 0) { return "参数无效"; }
+ if (propertyInfo == null)
+ propertyInfo = typeinfo.GetProperties().Where(x => x.PropertyType.Name != "List`1").ToArray();
+
+ // 不存在的字段直接移除
+ dic.Where(x => !propertyInfo.Any(p => p.Name == x.Key)).Select(s => s.Key).ToList().ForEach(f =>
+ {
+ dic.Remove(f);
+ });
+ string keyName = typeinfo.GetKeyName();
+ //移除主键
+ if (removerKey)
+ {
+ dic.Remove(keyName);
+ }
+ foreach (PropertyInfo property in propertyInfo)
+ {
+ //忽略与主键的字段不做验证
+ if (property.Name == keyName || (ignoreFields != null && ignoreFields.Contains(property.Name)))
+ continue;
+
+ //不在编辑中的列,是否也要必填
+ if (!dic.ContainsKey(property.Name))
+ {
+ //移除主键默认为新增数据,将不在编辑列中的有默认值的数据设置为默认值
+ //如果为true默认为添加功能,添加操作所有不能为空的列也必须要提交
+ if (property.GetCustomAttributes(typeof(RequiredAttribute)).Count() > 0
+ && property.PropertyType != typeof(int)
+ && property.PropertyType != typeof(long)
+ && property.PropertyType != typeof(byte)
+ && property.PropertyType != typeof(decimal)
+ )
+ {
+ return property.GetTypeCustomValue(x => x.Name) + "为必须提交项";
+ }
+ continue;
+ }
+ bool isEdit = property.ContainsCustomAttributes(typeof(EditableAttribute));
+ //不是编辑列的直接移除,并且不是主键
+ //removerKey=true,不保留主键,直接移除
+ //removerKey=false,保留主键,属性与主键不同的直接移除
+ // if (!isEdit && (removerKey || (!removerKey && property.Name != keyName)))
+ if (!isEdit)
+ {
+ if (property.GetCustomAttributes(typeof(RequiredAttribute)).Count() > 0)
+ {
+ return property.GetTypeCustomValue(x => x.Name) + "没有配置好Model为编辑列";
+ }
+ dic.Remove(property.Name);
+ continue;
+ }
+ ////移除忽略的不保存的数据
+ //if (property.ContainsCustomAttributes(typeof(JsonIgnoreAttribute)))
+ //{
+ // hash.Remove(property.Name);
+ // continue;
+ //}
+ //验证数据类型,不验证是否为空
+ var result = property.ValidationProperty(dic[property.Name], false);
+ if (!result.Item1)
+ return result.Item2;
+
+ //将所有空值设置为null
+ if (dic[property.Name] != null && dic[property.Name].ToString() == string.Empty)
+ dic[property.Name] = null;
+ }
+ return string.Empty;
+ }
+
+
+ private static object MapToInstance(this Type reslutType, object sourceEntity, PropertyInfo[] sourcePro, PropertyInfo[] reslutPro, string[] sourceFilterField, string[] reslutFilterField, string mapType = null)
+ {
+ mapType = mapType ?? GetMapType(reslutType);
+ if (sourcePro == null)
+ {
+ sourcePro = sourceEntity.GetType().GetProperties();
+ }
+ if (reslutPro == null)
+ {
+ reslutPro = reslutType.GetProperties(); ;
+ }
+
+ object newObj = Activator.CreateInstance(reslutType);
+
+ if (mapType == "Dictionary")
+ {
+ if (sourceFilterField != null && sourceFilterField.Length > 0)
+ {
+ sourcePro = sourcePro.Where(x => sourceFilterField.Contains(x.Name)).ToArray();
+ }
+ foreach (var property in sourcePro)
+ {
+ (newObj as System.Collections.IDictionary).Add(property.Name, property.GetValue(sourceEntity));
+ }
+ return newObj;
+ }
+
+ if (reslutFilterField != null && reslutFilterField.Count() > 0)
+ {
+ reslutPro.Where(x => reslutFilterField.Contains(x.Name));
+ }
+
+ foreach (var property in reslutPro)
+ {
+ PropertyInfo info = sourcePro.Where(x => x.Name == property.Name).FirstOrDefault();
+ if (!(info != null && info.PropertyType == property.PropertyType))
+ continue;
+ property.SetValue(newObj, info.GetValue(sourceEntity));
+ }
+ return newObj;
+ }
+ private static string GetMapType(Type type)
+ {
+ return typeof(Dictionary<,>) == type ? "Dictionary" : "entity";
+ }
+
+ ///
+ /// 将数据源映射到新的数据中,目前只支持List映射到List或TSource映射到TResult
+ /// 目前只支持Dictionary或实体类型
+ ///
+ ///
+ ///
+ ///
+ /// 只映射返回对象的指定字段,若为null则默认为全部字段
+ /// 只映射数据源对象的指定字段,若为null则默认为全部字段
+ ///
+ public static TResult MapToObject(this TSource source, Expression> resultExpression,
+ Expression> sourceExpression = null
+ ) where TResult : class
+ {
+ if (source == null)
+ return null;
+ string[] sourceFilterField = sourceExpression == null ? typeof(TSource).GetProperties().Select(x => x.Name).ToArray() : sourceExpression.GetExpressionProperty();
+ string[] reslutFilterField = resultExpression?.GetExpressionProperty();
+ if (!(source is System.Collections.IList))
+ return MapToInstance(typeof(TResult), source, null, null, sourceFilterField, reslutFilterField) as TResult;
+
+ Type sourceType = null;
+ Type resultType = null;
+ System.Collections.IList sourceList = source as System.Collections.IList;
+ sourceType = sourceList[0].GetType();
+ resultType = (typeof(TResult)).GenericTypeArguments[0];
+
+ System.Collections.IList reslutList = Activator.CreateInstance(typeof(TResult)) as System.Collections.IList;
+ PropertyInfo[] sourcePro = sourceType.GetProperties();
+ PropertyInfo[] resultPro = resultType.GetProperties();
+
+ string mapType = GetMapType(resultType);
+ for (int i = 0; i < sourceList.Count; i++)
+ {
+ var reslutobj = MapToInstance(resultType, sourceList[i], sourcePro, resultPro, sourceFilterField, reslutFilterField, mapType);
+ reslutList.Add(reslutobj);
+ }
+ return reslutList as TResult;
+ }
+
+ ///
+ /// 将一个实体的赋到另一个实体上,应用场景:
+ /// 两个实体,a a1= new a();b b1= new b(); a1.P=b1.P; a1.Name=b1.Name;
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 指定对需要的字段赋值,格式x=>new {x.Name,x.P},返回的结果只会对Name与P赋值
+ public static void MapValueToEntity(this TSource source, TResult result, Expression> expression = null) where TResult : class
+ {
+ if (source == null)
+ return;
+ string[] fields = expression?.GetExpressionToArray();
+ PropertyInfo[] reslutPro = fields == null ? result.GetType().GetProperties() : result.GetType().GetProperties().Where(x => fields.Contains(x.Name)).ToArray();
+ PropertyInfo[] sourcePro = source.GetType().GetProperties();
+ foreach (var property in reslutPro)
+ {
+ PropertyInfo info = sourcePro.Where(x => x.Name == property.Name).FirstOrDefault();
+ if (info != null && info.PropertyType == property.PropertyType)
+ {
+ property.SetValue(result, info.GetValue(source));
+ }
+ }
+ }
+
+
+
+
+
+ }
+
+ public class ArrayEntity
+ {
+ public string column1 { get; set; }
+ }
+
+ public enum FieldType
+ {
+ VarChar = 0,
+ NvarChar,
+ Int,
+ BigInt,
+ UniqueIdentifier
+ }
+
+ public enum EntityToSqlTempName
+ {
+ TempInsert = 0
+ }
+}
diff --git a/Infrastructure/Extensions/GenericExtension.cs b/Infrastructure/Extensions/GenericExtension.cs
new file mode 100644
index 0000000000000000000000000000000000000000..8b9f20a0d6e2153a0779045e3cd156a8092c3281
--- /dev/null
+++ b/Infrastructure/Extensions/GenericExtension.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace Infrastructure.Extensions
+{
+ ///
+ /// 泛型扩展
+ ///
+ public static class GenericExtension
+ {
+ public static bool Equal(this T x, T y)
+ {
+ return ((IComparable)(x)).CompareTo(y) == 0;
+ }
+
+ #region ToDictionary
+ ///
+ /// 将实体指定的字段写入字典
+ ///
+ ///
+ ///
+ ///
+ ///
+
+ public static Dictionary ToDictionary(this T t, Expression> expression) where T : class
+ {
+ Dictionary dic = new Dictionary();
+ string[] fields = expression.GetExpressionToArray();
+ PropertyInfo[] properties = expression == null ? t.GetType().GetProperties() : t.GetType().GetProperties().Where(x => fields.Contains(x.Name)).ToArray();
+
+ foreach (var property in properties)
+ {
+ var value = property.GetValue(t, null);
+ dic.Add(property.Name, value != null ? value.ToString() : "");
+ }
+ return dic;
+ }
+
+ public static Dictionary ToDictionary(this TInterface t, Dictionary dic = null) where T : class, TInterface
+ {
+ if (dic == null)
+ dic = new Dictionary();
+ var properties = typeof(T).GetProperties();
+ foreach (var property in properties)
+ {
+ var value = property.GetValue(t, null);
+ if (value == null) continue;
+ dic.Add(property.Name, value != null ? value.ToString() : "");
+ }
+ return dic;
+ }
+
+ #endregion
+
+
+ public static DataTable ToDataTable(this IEnumerable source, Expression> columns = null, bool contianKey = true)
+ {
+ DataTable dtReturn = new DataTable();
+ if (source == null) return dtReturn;
+
+ PropertyInfo[] oProps = typeof(T).GetProperties()
+ .Where(x => x.PropertyType.Name != "List`1").ToArray();
+ if (columns != null)
+ {
+ string[] columnArray = columns.GetExpressionToArray();
+ oProps = oProps.Where(x => columnArray.Contains(x.Name)).ToArray();
+ }
+ //移除自增主键
+ PropertyInfo keyType = oProps.GetKeyProperty();// oProps.GetKeyProperty()?.PropertyType;
+ if (!contianKey && keyType != null && (keyType.PropertyType == typeof(int) || keyType.PropertyType == typeof(long)))
+ {
+ oProps = oProps.Where(x => x.Name != keyType.Name).ToArray();
+ }
+
+ foreach (var pi in oProps)
+ {
+ var colType = pi.PropertyType;
+
+ if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
+ {
+ colType = colType.GetGenericArguments()[0];
+ }
+
+ dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
+ }
+ foreach (var rec in source)
+ {
+ var dr = dtReturn.NewRow();
+ foreach (var pi in oProps)
+ {
+ dr[pi.Name] = pi.GetValue(rec, null) == null
+ ? DBNull.Value
+ : pi.GetValue
+ (rec, null);
+ }
+ dtReturn.Rows.Add(dr);
+ }
+ return dtReturn;
+ }
+ }
+}
diff --git a/Infrastructure/Extensions/LambdaExtensions.cs b/Infrastructure/Extensions/LambdaExtensions.cs
new file mode 100644
index 0000000000000000000000000000000000000000..5de78e6a1d51121c7889364e0fac63de05c9a46e
--- /dev/null
+++ b/Infrastructure/Extensions/LambdaExtensions.cs
@@ -0,0 +1,504 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+ using Infrastructure.Const;
+
+ namespace Infrastructure.Extensions
+{
+ public static class LambdaExtensions
+ {
+ ///
+ /// 分页查询
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static IQueryable TakePage(this IQueryable queryable, int page, int size = 15)
+ {
+ return queryable.TakeOrderByPage(page, size);
+ }
+ ///
+ /// 分页查询
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static IQueryable TakeOrderByPage(this IQueryable queryable, int page, int size = 15, Expression>> orderBy = null)
+ {
+ if (page <= 0)
+ {
+ page = 1;
+ }
+ return Queryable.Take(Queryable.Skip(queryable.GetIQueryableOrderBy(orderBy.GetExpressionToDic()), (page - 1) * size), size);
+ }
+
+ ///
+ /// 创建lambda表达式:p=>true
+ ///
+ ///
+ ///
+ public static Expression> True()
+ {
+ return p => true;
+ }
+
+ ///
+ /// 创建lambda表达式:p=>false
+ ///
+ ///
+ ///
+ public static Expression> False()
+ {
+
+ return p => false;
+ }
+
+ public static ParameterExpression GetExpressionParameter(this Type type)
+ {
+
+ return Expression.Parameter(type, "p");
+ }
+ ///
+ /// 创建lambda表达式:p=>p.propertyName
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Expression> GetExpression(this string propertyName)
+ {
+ return propertyName.GetExpression(typeof(T).GetExpressionParameter());
+ }
+ ///
+ /// 创建委托有返回值的表达式:p=>p.propertyName
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Func GetFun(this string propertyName)
+ {
+ return propertyName.GetExpression(typeof(T).GetExpressionParameter()).Compile();
+ }
+
+ ///
+ /// 创建lambda表达式:p=>false
+ /// 在已知TKey字段类型时,如动态排序OrderBy(x=>x.ID)会用到此功能,返回的就是x=>x.ID
+ /// Expression> expression = x => x.CreateDate;指定了类型
+ ///
+ ///
+ ///
+ public static Expression> GetExpression(this string propertyName, ParameterExpression parameter)
+ {
+ if (typeof(TKey).Name == "Object")
+ return Expression.Lambda>(Expression.Convert(Expression.Property(parameter, propertyName), typeof(object)), parameter);
+ return Expression.Lambda>(Expression.Property(parameter, propertyName), parameter);
+ }
+ ///
+ /// 创建lambda表达式:p=>false
+ /// object不能确认字段类型(datetime,int,string),如动态排序OrderBy(x=>x.ID)会用到此功能,返回的就是x=>x.ID
+ /// Expression> expression = x => x.CreateDate;任意类型的字段
+ ///
+ ///
+ ///
+ public static Expression> GetExpression(this string propertyName)
+ {
+ return propertyName.GetExpression(typeof(T).GetExpressionParameter());
+ }
+
+ public static Expression> GetExpression(this string propertyName, ParameterExpression parameter)
+ {
+ return Expression.Lambda>(Expression.Convert(Expression.Property(parameter, propertyName), typeof(object)), parameter);
+ }
+
+
+
+ ///
+ ///
+ ///
+ ///
+ /// 字段名
+ /// 表达式的值
+ /// 创建表达式的类型,如:p=>p.propertyName != propertyValue
+ /// p=>p.propertyName.Contains(propertyValue)
+ ///
+ public static Expression> CreateExpression(this string propertyName, object propertyValue, LinqExpressionType expressionType)
+ {
+ return propertyName.CreateExpression(propertyValue, null, expressionType);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// 字段名
+ /// 表达式的值
+ /// 创建表达式的类型,如:p=>p.propertyName != propertyValue
+ /// p=>p.propertyName.Contains(propertyValue)
+ ///
+ private static Expression> CreateExpression(
+ this string propertyName,
+ object propertyValue,
+ ParameterExpression parameter,
+ LinqExpressionType expressionType)
+ {
+ Type proType = typeof(T).GetProperty(propertyName).PropertyType;
+ //创建节点变量如p=>的节点p
+ // parameter ??= Expression.Parameter(typeof(T), "p");//创建参数p
+ parameter = parameter ?? Expression.Parameter(typeof(T), "p");
+
+ //创建节点的属性p=>p.name 属性name
+ MemberExpression memberProperty = Expression.PropertyOrField(parameter, propertyName);
+ if (expressionType == LinqExpressionType.In)
+ {
+ if (!(propertyValue is System.Collections.IList list) || list.Count == 0) throw new Exception("属性值类型不正确");
+
+ bool isStringValue = true;
+ List