diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..29f81d81 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index ec8e482f..60961fb9 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,65 @@ -**WebFirst 代码生成器** - -- 在线生成entity、xml、dao、service、html、js、sql代码,减少70%以上的开发任务 -- 可以在线创建数据库和导出文档 -- 可在线建类并且生成表 -- 支持方案保存,模版管理 -- 超级流畅的性能 -
- - -**如何交流、反馈、参与贡献?** -- Github: https://github.com/donet5/WebFirst -- OSC Gitee:https://gitee.com/sunkaixuan/web-first -- [果糖官网] https://www.donet5.com/ -- [使用文档] https://www.donet5.com/Doc/11 -- 官方QQ群:958343000 -- 技术讨论、二次开发等咨询、问题和建议,请移步到人人开源社区,我会在第一时间进行解答和回复 -- 如需关注项目最新动态,请Watch、Star项目,同时也是对项目最好的支持 -- 微信扫码加好友【果糖网】,与作者互动

-![输入图片说明](https://www.donet5.com/_theme/img/addWX.jpg "加微信") - - **本地部署代码生成器** -- 通过git下载源码 -- F5直接运行项目 -- 安装VS2019 c#,则可启动项目 -- 项目访问路径:默认 - -**代码生成器演示效果图:** -![输入图片说明](https://www.donet5.com/_theme/ueditor/utf8-net/net/upload/image/20211001/6376869443519224327257971.png "用例") +## 框架描述 +WebFirst 是果糖大数据团队开发的新一代 高性能 代码生成器&数据库设计工具,由.net core + sqlsugar 开发 导入1000个表只要1-2秒,用法简单,功能强大,支持多种数据库 +### 图片预览 + +![输入图片说明](https://www.donet5.com//_theme/ueditor/utf8-net/net/upload/image/20211009/6376941449795119979562201.png "用例") + +### 功能预览 + +1、 建库、CodeFirst方式在线建表,没用到CodeFirst的用户可以用工具轻松体验,支持公共字段 + +2、导出EXCEL文档,把每个表的数据导出来 + +3、模版管理 可以自个添加修改模版,使用的是Razor模版引擎对C#程序员更加友好 + +4、方案管理,可以创建自已的生成方案,修改方案 + +5、支持扩展模版属性,支持生成更加丰富的前端代码 + +6、支持生成解决方案 + +7、支持生成附加文件,支持文件后缀 + +8、支持视图 + +9、支持自定义数据类型 + +10、支持多种数据库 MYSQL PGSQL SQLITE SQLSERVE ORCLE 达梦 + +### 功能特色 +1、生成器与你具体的项目解耦,可以独立管理多个解决方案 + +2、支持一键生成多个解决方案 + +3、支持EXE方式和Web方式部署 + +## 使用场景 + +1、提高工作效率 + +我们都知道一个CRUD其实如果有代码生成器的话只需要几分钟就可以把完整的功能做完,如果用手去写那么可能就要花掉一整天的时间,多出来的这些时间学学技术多好 + +2、大量重复有共性的功能 + +使用代码生成器最重要的就是减少大量重复的工作,比如我们有 数据库model 有表单model 有Grid绑定的 model 光写这些MODEL就很头痛,要写各种特性 + +## 使用教程 +### 配置实体 +1、通过数据库导入实体: 菜单【配置实体(表建类模式)】 + +2、在线建实体 : 菜单【配置实体(类建表模式)】 + +3、通过SQL建实体: 菜单【配置实体(视图模式)】 +### 一键生成 +配置实体后就可以使用自带的一键生成功能来生成用例代码,通过自带方案和模版的配置可以快速了解框架 +### 方案管理 +一键生成可以生成多个方案,方案 包含: 模版、路径、文件名、文件后缀 等 可以理解为某个模版的生成配置 +### 模版管理 +模版是方案的一个重要参数,什么样的模版 生成什么样的文件内容,比如 实体类就编写实体类模版 ,业务就编写业务模版 + + +## 下载软件 +[WebFirst最新版本下载](https://www.donet5.com/Doc/11/2388) + +## QQ群交流 +QQ交流群: 958343000 diff --git a/SoEasyPlatform.sln b/SoEasyPlatform.sln index 5c8e535b..48f17d2a 100644 --- a/SoEasyPlatform.sln +++ b/SoEasyPlatform.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30523.141 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32414.318 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SoEasyPlatform", "SoEasyPlatform\SoEasyPlatform.csproj", "{D4E4101E-81B5-40F8-903D-D6E069250841}" EndProject diff --git a/SoEasyPlatform/Apis/CodeTableApp/CodeTableController.cs b/SoEasyPlatform/Apis/CodeTableApp/CodeTableController.cs index 6ba4e39a..5428dd48 100644 --- a/SoEasyPlatform/Apis/CodeTableApp/CodeTableController.cs +++ b/SoEasyPlatform/Apis/CodeTableApp/CodeTableController.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using System.Threading.Tasks; using AutoMapper; using Microsoft.AspNetCore.Mvc; @@ -228,7 +229,7 @@ public ActionResult> SaveCodeType([FromForm] CodeTypeViewModel if (errorResult != null) return errorResult; CodeType codetype = new CodeType() { - Id = 0, + Id =Convert.ToInt32(model.Id), CSharepType = model.CSharepType, Name = model.Name, Sort = model.Sort.Value @@ -243,17 +244,18 @@ public ActionResult> SaveCodeType([FromForm] CodeTypeViewModel result.Data = model.DbType + "格式不正确"; return result; } - - CodeTypeDb.Insert(codetype); + var x = Db.Storageable(codetype).ToStorage(); + x.AsUpdateable.ExecuteCommand(); + x.AsInsertable.ExecuteCommand(); result.IsSuccess = true; - result.Data = Pubconst.MESSAGEADDSUCCESS; + result.Data =x.InsertList.Any()? Pubconst.MESSAGEADDSUCCESS:Pubconst.MESSAGESAVESUCCESS; return result; } #endregion #region Create File /// - /// 生成实体 + /// 创建方案 /// /// [HttpPost] @@ -319,14 +321,17 @@ public ActionResult> CreateFileByProjectId([FromForm] ProjectVie var tableList = CodeTableDb.GetList(it => tableids.Contains(it.Id)); int dbId = tableList.First().DbId; var connection = base.GetTryDb(dbId); - List genList = GetGenList(tableList, CodeTypeDb.GetList(), connection.CurrentConnectionConfig.DbType); + List genList = GetGenList(tableList, CodeTypeDb.GetList(),connection, connection.CurrentConnectionConfig.DbType); string key = TemplateHelper.EntityKey + template.GetHashCode(); foreach (var item in genList) { item.name_space = GetNameSpace(project.FileModel, item.name_space); var html = TemplateHelper.GetTemplateValue(key, template, item); var fileName = GetFileName(project, item); - FileSugar.CreateFileReplace(fileName, html, Encoding.UTF8); + if (fileName.Last() != '.') + { + FileSugar.CreateFileReplace(fileName, html, Encoding.UTF8); + } } OpenPath(disOpen, project); ProjectController_Common.CreateProject(project.Id, model.DbId.Value); @@ -374,7 +379,7 @@ public ActionResult> CreateTables([FromForm] string model, [From var list = Newtonsoft.Json.JsonConvert.DeserializeObject>(model); var oldList = CodeTableDb.AsQueryable().In(list.Select(it => it.Id).ToList()).ToList(); base.Check(oldList.Any(it => it.IsLock), string.Join(",", oldList.Where(it => it.IsLock).Select(it => it.ClassName)) + "是锁表状态禁止建表"); - List genList = GetGenList(oldList, CodeTypeDb.GetList(), tableDb.CurrentConnectionConfig.DbType); + List genList = GetGenList(oldList, CodeTypeDb.GetList(),tableDb, tableDb.CurrentConnectionConfig.DbType); foreach (var item in genList) { item.PropertyGens = item.PropertyGens.Where(it => it.IsIgnore == false).ToList(); @@ -430,6 +435,102 @@ public ActionResult> CreateTables([FromForm] string model, [From return result; } + + + /// + ////结构对比 + /// + /// + [HttpPost] + [ExceptionFilter] + [Route("GetTableDiff")] + public ActionResult> GetTableDiff([FromForm] string model, [FromForm] int dbid) + { + var tableDb = base.GetTryDb(dbid); + var result = new ApiResult(); + List tableDifferences = new List(); + if (!string.IsNullOrEmpty(model)) + { + var list = Newtonsoft.Json.JsonConvert.DeserializeObject>(model); + var oldList = CodeTableDb.AsQueryable().In(list.Select(it => it.Id).ToList()).ToList(); + base.Check(oldList.Any(it => it.IsLock), string.Join(",", oldList.Where(it => it.IsLock).Select(it => it.ClassName)) + "是锁表状态禁止建表"); + List genList = GetGenList(oldList, CodeTypeDb.GetList(),tableDb, tableDb.CurrentConnectionConfig.DbType); + foreach (var item in genList) + { + item.PropertyGens = item.PropertyGens.Where(it => it.IsIgnore == false).ToList(); + foreach (var property in item.PropertyGens) + { + if (property.IsSpecialType) + { + property.Type = "string"; + } + } + } + string key = TemplateHelper.EntityKey + SyntaxTreeHelper.TemplateString.GetHashCode(); + foreach (var item in genList) + { + var classString = TemplateHelper.GetTemplateValue(key, SyntaxTreeHelper.TemplateString, item); + var type = SyntaxTreeHelper.GetModelTypeByClass(classString, item.ClassName); + tableDb.CurrentConnectionConfig.ConfigureExternalServices = new ConfigureExternalServices() + { + EntityNameService = (type, info) => + { + if (info.EntityName == item.ClassName || (info.EntityName == null && info.DbTableName == item.ClassName)) + { + info.EntityName = item.ClassName; + info.DbTableName = item.TableName; + info.TableDescription = item.Description; + } + }, + EntityService = (type, info) => + { + if (info.EntityName == item.ClassName) + { + var column = item.PropertyGens.FirstOrDefault(it => it.PropertyName == info.PropertyName); + info.DbColumnName = column.DbColumnName; + info.ColumnDescription = column.Description; + info.IsNullable = column.IsNullable; + info.Length = Convert.ToInt32(column.Length); + info.DecimalDigits = Convert.ToInt32(column.DecimalDigits); + info.IsPrimarykey = column.IsPrimaryKey; + info.IsIdentity = column.IsIdentity; + info.IsIgnore = column.IsIgnore; + info.DataType = column.DbType; + if (tableDb.CurrentConnectionConfig.DbType == DbType.Sqlite && info.IsIdentity) + { + info.DataType = "integer"; + } + } + } + }; + if(tableDb.DbMaintenance.IsAnyTable(item.TableName, false)) + { + var diff = tableDb.CodeFirst.GetDifferenceTables(type).ToDiffString(); + if (diff != null && !diff.Contains("No change")) + { + tableDifferences.Add(diff); + } + } + } + + } + if (tableDifferences.Count == 0) + { + result.Data = "此操作没有风险,可以继续!!"; + } + else + { + result.Data = string.Join("", tableDifferences).Replace("\n","
"); + } + result.Data = result.Data.Replace( "
----", "

"); + result.Data = result.Data.Replace("----", "

"); + result.Data = result.Data.Replace("Table:", "表名:"); + result.Data = result.Data.Replace("Add column", "添加列"); + result.Data = result.Data.Replace("Update column", "更新列"); + result.Data = result.Data.Replace("Delete column", "删除列"); + result.IsSuccess = true; + return result; + } #endregion #region Update entity by db @@ -483,7 +584,8 @@ public ActionResult> SaveCodetableImport([FromForm] int dbid, [F CodeTableId = entity.Id, CodeType = typeInfo.CodeType.Name, Length = typeInfo.DbTypeInfo.Length, - DecimalDigits = typeInfo.DbTypeInfo.DecimalDigits + DecimalDigits = typeInfo.DbTypeInfo.DecimalDigits, + DefaultValue = columnInfo.DefaultValue }; code.ColumnInfoList.Add(column); } @@ -614,7 +716,7 @@ public ActionResult> Copy([FromForm] ProjectViewModel2 model) var tableList = CodeTableDb.GetList(it => tableids.Contains(it.Id)); int dbId = tableList.First().DbId; var connection = base.GetTryDb(dbId); - List genList = GetGenList(tableList, CodeTypeDb.GetList(), connection.CurrentConnectionConfig.DbType); + List genList = GetGenList(tableList, CodeTypeDb.GetList(),connection, connection.CurrentConnectionConfig.DbType); string key = TemplateHelper.EntityKey + template.GetHashCode(); foreach (var item in genList.Take(1)) { @@ -662,7 +764,7 @@ public ActionResult> SaveCommField([FromForm] string Field,[Fr IsIdentity = filedItem.IsIdentity, IsPrimaryKey = filedItem.IsPrimaryKey, Required = filedItem.Required, - + Description= filedItem.Description }); } } diff --git a/SoEasyPlatform/Apis/CodeTableApp/CodeTableController_CreateFile.cs b/SoEasyPlatform/Apis/CodeTableApp/CodeTableController_CreateFile.cs index 0abb70be..2cd74f7a 100644 --- a/SoEasyPlatform/Apis/CodeTableApp/CodeTableController_CreateFile.cs +++ b/SoEasyPlatform/Apis/CodeTableApp/CodeTableController_CreateFile.cs @@ -1,5 +1,6 @@ using AutoMapper; using Microsoft.AspNetCore.Mvc; +using Npgsql.TypeHandlers.DateTimeHandlers; using SqlSugar; using System; using System.Collections.Generic; @@ -52,13 +53,26 @@ private static void OpenPath(string path) } } - private List GetGenList(List tableList, List types,SqlSugar.DbType databasedbType) + private List GetGenList(List tableList, List types, SqlSugarClient db, SqlSugar.DbType databasedbType) { List result = new List(); var mapping = Db.Queryable().ToList(); var tags = Db.Queryable().ToList(); + if (databasedbType == DbType.MySql) + { + var timestamp = types.FirstOrDefault(it => it.Name == "timestamp"); + if (timestamp != null) + { + timestamp.CSharepType = "DateTime"; + } + } foreach (var item in tableList) { + var tableColumns = new List { }; + if (db.DbMaintenance.IsAnyTable(item.TableName,false)) + { + tableColumns=db.DbMaintenance.GetColumnInfosByTableName(item.TableName, false); + } EntitiesGen gen = new EntitiesGen() { ClassName = item.ClassName, @@ -84,7 +98,8 @@ private List GetGenList(List tableList, List t Length = 0, DecimalDigits = 0, IsIgnore = true, - CodeType=column.CodeType + CodeType=column.CodeType, + DefaultValue=column.DefaultValue }; var mappings= mapping.Where(it => item.DbId == it.DbId && it.TableName == item.ClassName && it.ColumnName == column.ClassProperName).ToList(); ; proGen.MappingProperties = tags.Where(it => mappings.Any(x => x.TagId == it.Id + "")).ToList(); @@ -93,6 +108,11 @@ private List GetGenList(List tableList, List t else { var dbType = GetTypeInfoByDatabaseType(codeType.DbType, databasedbType); + var dbColumnInfo = tableColumns.FirstOrDefault(it => it.DbColumnName.ToLower() == column.DbColumnName.ToLower()); + if (!string.IsNullOrEmpty(dbColumnInfo?.OracleDataType)) + { + dbColumnInfo.DataType = dbColumnInfo.OracleDataType; + } PropertyGen proGen = new PropertyGen() { DbColumnName = column.DbColumnName, @@ -104,9 +124,13 @@ private List GetGenList(List tableList, List t IsNullable = column.Required == false, DbType = dbType.Name, Length = dbType.Length, + Db_Length = dbColumnInfo?.Length, + Db_DecimalDigits = dbColumnInfo?.DecimalDigits, + Db_DateType=dbColumnInfo?.DataType, DecimalDigits = dbType.DecimalDigits, IsSpecialType= IsSpecialType(column), - CodeType= column.CodeType + CodeType= column.CodeType, + DefaultValue=column.DefaultValue }; var mappings = mapping.Where(it => item.DbId == it.DbId && it.TableName == item.ClassName && it.ColumnName == column.ClassProperName).ToList(); ; proGen.MappingProperties = tags.Where(it => mappings.Any(x => x.TagId == it.Id + "")).ToList(); @@ -150,6 +174,7 @@ private DbTypeInfo GetTypeInfoByDatabaseType(DbTypeInfo[] dbType, DbType databas break; case DbType.SqlServer: mstypes= SqlSugar.SqlServerDbBind.MappingTypesConst.Select(it => it.Key.ToLower()).ToList(); + mstypes.Add("xml"); break; case DbType.Sqlite: mstypes = SqlSugar.SqliteDbBind.MappingTypesConst.Select(it => it.Key.ToLower()).ToList(); @@ -158,6 +183,12 @@ private DbTypeInfo GetTypeInfoByDatabaseType(DbTypeInfo[] dbType, DbType databas mstypes = SqlSugar.OracleDbBind.MappingTypesConst.Select(it => it.Key.ToLower()).ToList(); break; case DbType.PostgreSQL: + if (dbType.Any(it => it.Name == "blob")) + { + var list = new List { new DbTypeInfo() { Name = "bit" } }; + list.AddRange(dbType); + dbType = list.ToArray(); + } mstypes = SqlSugar.PostgreSQLDbBind.MappingTypesConst.Select(it => it.Key.ToLower()).ToList(); break; case DbType.Dm: @@ -197,9 +228,25 @@ private string GetFileName(Project project, EntitiesGen item) { p = null; } - if (!string.IsNullOrEmpty(project.NameFormat)) + if (project.NameFormat != null && project.NameFormat.Contains("@(") && project.NameFormat.Contains(")")) { - name = string.Format(project.NameFormat, item.ClassName); + var format = project.NameFormat.Replace("{0}", "Model.ClassName"); + name = TemplateHelper.GetTemplateValue(project.NameFormat + "format", format, item); + } + else if (!string.IsNullOrEmpty(project.NameFormat)) + { + if (project.NameFormat.Contains("{TableName}")) + { + name = project.NameFormat.Replace("{TableName}",item.TableName); + } + else if (project.NameFormat.Contains("{ClassName}")) + { + name = project.NameFormat.Replace("{ClassName}", item.ClassName); + } + else + { + name = string.Format(project.NameFormat, item.ClassName); + } } return FileSugar.MergeUrl(project.Path, name + p + project.FileSuffix); } diff --git a/SoEasyPlatform/Apis/CodeTableApp/CodeTableController_Export.cs b/SoEasyPlatform/Apis/CodeTableApp/CodeTableController_Export.cs index 9a93a88d..31a377ca 100644 --- a/SoEasyPlatform/Apis/CodeTableApp/CodeTableController_Export.cs +++ b/SoEasyPlatform/Apis/CodeTableApp/CodeTableController_Export.cs @@ -17,7 +17,7 @@ private DataTable [] Export(string model, SqlSugarClient tableDb) { var list = Newtonsoft.Json.JsonConvert.DeserializeObject>(model); var oldList = CodeTableDb.AsQueryable().In(list.Select(it => it.Id).ToList()).ToList(); - List genList = GetGenList(oldList, CodeTypeDb.GetList(), tableDb.CurrentConnectionConfig.DbType); + List genList = GetGenList(oldList, CodeTypeDb.GetList(),tableDb, tableDb.CurrentConnectionConfig.DbType); List datatables = new List(); foreach (var item in genList) { @@ -31,6 +31,7 @@ private DataTable [] Export(string model, SqlSugarClient tableDb) dt.Columns.Add("可空"); dt.Columns.Add("长度"); dt.Columns.Add("精度"); + dt.Columns.Add("默认值"); dt.Columns.Add("表名"); ; dt.Columns.Add("表描述"); foreach (var it in item.PropertyGens) @@ -48,6 +49,7 @@ private DataTable [] Export(string model, SqlSugarClient tableDb) dr["可空"] = it.IsNullable ? "是" : ""; dr["长度"] = it.Length; dr["精度"] = it.DecimalDigits; + dr["默认值"] = it.DefaultValue; dt.Rows.Add(dr); } diff --git a/SoEasyPlatform/Apis/CodeTableApp/CodeTableController_SaveCodeTableToDb.cs b/SoEasyPlatform/Apis/CodeTableApp/CodeTableController_SaveCodeTableToDb.cs index d1ad14b0..7e14d8d7 100644 --- a/SoEasyPlatform/Apis/CodeTableApp/CodeTableController_SaveCodeTableToDb.cs +++ b/SoEasyPlatform/Apis/CodeTableApp/CodeTableController_SaveCodeTableToDb.cs @@ -16,6 +16,15 @@ public partial class CodeTableController : BaseController { private void SaveCodeTableToDb(CodeTableViewModel viewModel) { + if (!string.IsNullOrEmpty(viewModel.TableName)) + { + viewModel.TableName = viewModel.TableName.Trim(); + } + if (!string.IsNullOrEmpty(viewModel.ClassName)) + { + viewModel.ClassName = viewModel.ClassName.Trim(); + } + base.Check(string.IsNullOrEmpty(viewModel.TableName) || string.IsNullOrEmpty(viewModel.ClassName), "表名或者实体类名必须填一个"); viewModel.ColumnInfoList = viewModel.ColumnInfoList .Where(it => !string.IsNullOrEmpty(it.ClassProperName) || !string.IsNullOrEmpty(it.DbColumnName)).ToList(); @@ -24,6 +33,10 @@ private void SaveCodeTableToDb(CodeTableViewModel viewModel) AutoFillTable(dbTable); var dbColumns = mapper.Map>(viewModel.ColumnInfoList); AutoFillColumns(dbColumns); + if (dbColumns.Where(it=>!string.IsNullOrEmpty(it.DbColumnName)).GroupBy(it => it.DbColumnName.ToLower()).Any(it => it.Count() > 1)) + { + base.Check(true, "存在重复列不能保存"); + } if (viewModel.Id == null || viewModel.Id == 0) { CheckAddName(viewModel, CodeTableDb); @@ -98,6 +111,14 @@ private void AutoFillColumns(List dbColumns) { item.DbColumnName = item.ClassProperName; } + if (!string.IsNullOrEmpty(item.ClassProperName)) + { + item.ClassProperName = item.ClassProperName.Trim(); + } + if (!string.IsNullOrEmpty(item.DbColumnName)) + { + item.DbColumnName = item.DbColumnName.Trim(); + } } } diff --git a/SoEasyPlatform/Apis/CodeTableApp/CodeTableController_SaveCodetableImport.cs b/SoEasyPlatform/Apis/CodeTableApp/CodeTableController_SaveCodetableImport.cs index c49b95dc..f84aaac0 100644 --- a/SoEasyPlatform/Apis/CodeTableApp/CodeTableController_SaveCodetableImport.cs +++ b/SoEasyPlatform/Apis/CodeTableApp/CodeTableController_SaveCodetableImport.cs @@ -17,10 +17,30 @@ public partial class CodeTableController : BaseController private SortTypeInfo GetEntityType(List types, DbColumnInfo columnInfo, CodeTableController codeTableController,DbType dbtype) { var typeInfo = types.FirstOrDefault(y => y.DbType.Any(it => it.Name.Equals(columnInfo.DataType, StringComparison.OrdinalIgnoreCase))); - if (typeInfo == null) + if (typeInfo == null && (columnInfo.DataType + "").ToLower() == "double") + { + var type = types.First(it => it.Name == "decimal_18_4"); + return new SortTypeInfo() { CodeType = type, DbTypeInfo = type.DbType[0] }; + } + else if (typeInfo == null && columnInfo.DataType == "int unsigned") + { + var type = types.First(it => it.Name == "int"); + return new SortTypeInfo() { CodeType = type, DbTypeInfo = type.DbType[0] }; + } + else if (typeInfo == null) { var type = types.First(it => it.Name == "string100"); - return new SortTypeInfo() { CodeType= type, DbTypeInfo= type.DbType[0] }; + return new SortTypeInfo() { CodeType = type, DbTypeInfo = type.DbType[0] }; + } + else if (columnInfo.DataType == "json") + { + var type = types.First(it => it.Name.ToLower() == "string2000"); + return new SortTypeInfo() { CodeType = type, DbTypeInfo = type.DbType[0] }; + } + else if (columnInfo.DataType == "timestamp" && dbtype != DbType.SqlServer) + { + var type = types.First(it => it.Name.ToLower() == "datetime"); + return new SortTypeInfo() { CodeType = type, DbTypeInfo = type.DbType[0] }; } else { @@ -32,11 +52,27 @@ private SortTypeInfo GetEntityType(List types, DbColumnInfo columnInfo SortTypeInfo item = new SortTypeInfo(); item.DbTypeInfo = cstype; item.CodeType = type; - item.Sort = GetSort(cstype,type,columnInfo,dbtype); + item.Sort = GetSort(cstype, type, columnInfo, dbtype); SortTypeInfoList.Add(item); } } - var result= SortTypeInfoList.OrderByDescending(it=>it.Sort).First(); + var result = SortTypeInfoList.Where(it => it.CodeType.Name != "json_default").OrderByDescending(it => it.Sort).FirstOrDefault(); + if (result == null) + { + throw new Exception($"没有匹配到类型{columnInfo.DataType} 来自 {columnInfo.TableName} 表 {columnInfo.DbColumnName} ,请到类型管理添加"); + } + if (result.CodeType.Name == "guid" && columnInfo.DataType == "char" && columnInfo.Length != 36) + { + result = SortTypeInfoList.FirstOrDefault(it => it.CodeType.Name == "string100"); + } + if (dbtype == DbType.PostgreSQL) + { + if (columnInfo.DataType == "bit") + { + var type = types.First(it => it.Name.ToLower() == "bytearray"); + return new SortTypeInfo() { CodeType = type, DbTypeInfo = type.DbType[0] }; + } + } return result; } } diff --git a/SoEasyPlatform/Apis/ProjectApp/ProjectController_Common.cs b/SoEasyPlatform/Apis/ProjectApp/ProjectController_Common.cs index f9ab431f..7a16fdf4 100644 --- a/SoEasyPlatform/Apis/ProjectApp/ProjectController_Common.cs +++ b/SoEasyPlatform/Apis/ProjectApp/ProjectController_Common.cs @@ -42,6 +42,12 @@ public static void CreateProject(Project project,int dbid=0) var db = DbScoped.Sugar.Queryable().InSingle(dbid); fileInfo.Content = fileInfo.Content.Replace("[请设置DbType]","SqlSugar.DbType."+db.DbType+"").Replace("[请设置ConStr]", "@@\""+db.Connection.Replace("@","@@")+"\""); } + else if (dbid > 0 && fileInfo.Content.Contains("[ConStr]")) + { + var db = DbScoped.Sugar.Queryable().InSingle(dbid); + fileInfo.Content = fileInfo.Content.Replace("[DbType]", db.DbType+"" ) + .Replace("[ConStr]", db.Connection.Replace("@", "@@") ); + } var context = fileInfo.Content; if (!string.IsNullOrEmpty(project.Reference)) { @@ -63,7 +69,7 @@ public static void CreateProject(Project project,int dbid=0) } var html = TemplateHelper.GetTemplateValue(context, context, jsonItem); var name = (jsonItem as IDictionary)["name"]; - var fileName = FileSugar.MergeUrl(project.Path, name + "." + fileInfo.Suffix.TrimStart('.')); + var fileName = FileSugar.MergeUrl(project.Path,fileInfo.Directory, name + "." + fileInfo.Suffix.TrimStart('.')); if (!FileSugar.IsExistFile(fileName)) FileSugar.CreateFile(fileName, html); if (fileName.EndsWith(".csproj")) diff --git a/SoEasyPlatform/Apis/ProjectGroupApp/ProjectGroupController.cs b/SoEasyPlatform/Apis/ProjectGroupApp/ProjectGroupController.cs new file mode 100644 index 00000000..5883ba8d --- /dev/null +++ b/SoEasyPlatform/Apis/ProjectGroupApp/ProjectGroupController.cs @@ -0,0 +1,205 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using AutoMapper; +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json.Linq; +using SoEasyPlatform.Models.ViewModel; +using SqlSugar; + +namespace SoEasyPlatform.Apis +{ + /// + /// 虚拟类配置 + /// + [Route("api/[controller]")] + [ApiController] + public partial class ProjectGroupController : BaseController + { + IMapper _mapper; + public ProjectGroupController(IMapper mapper) : base(mapper) + { + _mapper = mapper; + } + /// + /// 获取解决方案 + /// + /// + [HttpPost] + [Route("GetProjectGroupList")] + public ActionResult>> GetProjectGroupList([FromForm] ProjectGroupViewModel model) + { + model.PageSize = 20; + var result = new ApiResult>(); + result.Data = new TableModel(); + int count = 0; + var list = this.Db.Queryable() + .WhereIF(!string.IsNullOrEmpty(model.Name), it => it.Name.Contains(model.Name)) + .OrderBy(it => it.Sort) + .OrderBy(it => it.Id) + .ToPageList(model.PageIndex, model.PageSize, ref count); + var codeGridList = mapper.Map>(list); + result.Data.Rows = codeGridList; + result.Data.Total = count; + result.Data.PageSize = model.PageSize; + result.Data.PageNumber = model.PageIndex; + result.IsSuccess = true; + return result; + } + + /// + /// 添加解决方案 + /// + /// + [HttpPost] + [FormValidateFilter] + [Route("SaveProjectGroup")] + public ActionResult> SaveProjectGroup([FromForm] ProjectGroupViewModel model) + { + var result = new ApiResult(); + JsonResult errorResult = base.ValidateModel(model.Id); + if (errorResult != null) return errorResult; + var isNoUpdatProjectIds = model.ProjectNames == "noupdate"; + if (isNoUpdatProjectIds) + { + model.ProjectNames = "0"; + } + ProjectGroup ProjectGroup = new ProjectGroup() + { + Id = Convert.ToInt32(model.Id), + Name = model.Name, + Sort = Convert.ToInt32(model.Sort), + SolutionPath=model.SolutionPath, + ProjectIds=model.ProjectNames.Split(',').Select(it=>Convert.ToInt32(it)).ToArray(), + ProjectNames = String.Join(",", Db.Queryable().In(model.ProjectNames.Split(',').Select(it => Convert.ToInt32(it)).ToArray()).Select(it => it.ProjentName).ToArray()) + }; + var x = Db.Storageable(ProjectGroup).ToStorage(); + x.AsUpdateable.IgnoreColumnsIF(isNoUpdatProjectIds, it=>new { it.ProjectIds,it.ProjectNames}).ExecuteCommand(); + x.AsInsertable.ExecuteCommand(); + result.IsSuccess = true; + result.Data = x.InsertList.Any() ? Pubconst.MESSAGEADDSUCCESS : Pubconst.MESSAGESAVESUCCESS; + return result; + } + + /// + /// 执行一键生成 + /// + /// + [HttpPost] + [Route("BuilderProjects")] + public ActionResult> BuilderProjects([FromForm] string model, [FromForm] int pgid, [FromForm] int dbid) + { + var result = new ApiResult(); + if (!string.IsNullOrEmpty(model)) + { + var group = Db.Queryable().InSingle(pgid); + var projectids = group.ProjectIds; + var list= Db.Queryable().In(projectids).OrderBy(it => it.ModelId).ToList(); + try + { + Db.BeginTran(); + foreach (var item in list) + { + var name = System.IO.Path.GetFileName(item.Path); + item.Path = System.IO.Path.Combine(group.SolutionPath,name); + Db.Updateable(item).ExecuteCommand(); + new CodeTableController(null).CreateFileByProjectId(new ProjectViewModel2 + { + + Tables = model, + ProjectId = item.Id, + DbId = dbid, + ModelId = item.ModelId + }, list.Last() == item); + } + //Db.Updateable(list).ExecuteCommand(); + Db.CommitTran(); + } + catch (Exception ex) + { + Db.RollbackTran(); + throw ex; + } + } + result.IsSuccess = true; + return result; + } + /// + /// 执行一键生成通过下载 + /// + /// + [HttpPost] + [Route("BuilderProjectsByHttp")] + public ApiResult BuilderProjectsByHttp([FromForm] string model, [FromForm] int pgid, [FromForm] int dbid) + { + var result = new ApiResult(); + if (!string.IsNullOrEmpty(model)) + { + var group = Db.Queryable().InSingle(pgid); + var projectids = group.ProjectIds; + var list = Db.Queryable().In(projectids).OrderBy(it => it.ModelId).ToList(); + result.Data = group.SolutionPath; + try + { + Db.BeginTran(); + foreach (var item in list) + { + var name = System.IO.Path.GetFileName(item.Path); + item.Path = System.IO.Path.Combine(group.SolutionPath, name); + + + + Db.Updateable(item).ExecuteCommand(); + new CodeTableController(null).CreateFileByProjectId(new ProjectViewModel2 + { + Tables = model, + ProjectId = item.Id, + DbId = dbid, + ModelId = item.ModelId + }, false); + } + + if (!System.IO.Directory.Exists(System.IO.Path.Combine("wwwroot", "temp"))) + { + System.IO.Directory.CreateDirectory(System.IO.Path.Combine("wwwroot", "temp"));//不存在就创建文件夹 + } + var zipName = $"{DateTime.Now.ToString("yyyy-MM-dd-hh-mm-ss")}.zip"; + var zipPath = System.IO.Path.Combine("wwwroot", "temp", zipName); + ZipHelper.ZipFileDirectory(result.Data, zipPath); + result.Data = System.IO.Path.Combine("temp", zipName).Replace("\\","/"); + + Db.CommitTran(); + } + catch (Exception ex) + { + Db.RollbackTran(); + throw ex; + } + } + result.IsSuccess = true; + + return result; + } + + /// + /// 删除解决方案 + /// + /// + [HttpPost] + [Route("deleteProjectGroup")] + public ActionResult> deleteProjectGroup([FromForm] string model) + { + var result = new ApiResult(); + if (!string.IsNullOrEmpty(model)) + { + var list = Newtonsoft.Json.JsonConvert.DeserializeObject>(model); + Db.Deleteable().In(list.Select(it => it.Id).ToList()).ExecuteCommand(); + } + result.IsSuccess = true; + return result; + } + } +} diff --git a/SoEasyPlatform/Apis/SystemApp/SystemController.cs b/SoEasyPlatform/Apis/SystemApp/SystemController.cs index df6cbbd8..659d7449 100644 --- a/SoEasyPlatform/Apis/SystemApp/SystemController.cs +++ b/SoEasyPlatform/Apis/SystemApp/SystemController.cs @@ -49,12 +49,15 @@ public ActionResult>> GetDbType() List trees = new List(); foreach (DbType type in Enum.GetValues(typeof(DbType))) { - trees.Add(new TreeModel() + if (type != DbType.MySqlConnector && type != DbType.Custom && type != DbType.Access && type != DbType.Oscar) { - Id = type.ToString(), - Title = type.ToString(), - IsSelectable = true - }); + trees.Add(new TreeModel() + { + Id = type.ToString(), + Title = type.ToString(), + IsSelectable = true + }); + } } ApiResult> result = new ApiResult>(); result.Data = trees; @@ -126,10 +129,11 @@ public ActionResult>> GetFileInfo() [HttpPost] [AuthorizeFilter] [Route("GetProject")] - public ActionResult>> GetProject(int typeId) + public ActionResult>> GetProject(int? typeId) { List trees = new List(); - var databses = ProjectDb.GetList(it => it.ModelId.Equals(typeId)); + var databses = typeId==null? ProjectDb.GetList(): ProjectDb.GetList(it => it.ModelId.Equals(typeId)); + foreach (var db in databses) { trees.Add(new TreeModel() diff --git a/SoEasyPlatform/Code/AppStart/InitTable.cs b/SoEasyPlatform/Code/AppStart/InitTable.cs index 429e6bae..f37beded 100644 --- a/SoEasyPlatform/Code/AppStart/InitTable.cs +++ b/SoEasyPlatform/Code/AppStart/InitTable.cs @@ -6,7 +6,7 @@ using SqlSugar; namespace SoEasyPlatform { - public class InitTable + public partial class InitTable { /// /// 默认实体ID @@ -59,6 +59,8 @@ public void Start() InitTagProperty(db); InitOther(db); + + InitProjects(db); } private void InitOther(SqlSugarClient db) @@ -78,6 +80,8 @@ private void InitCommonField(SqlSugarClient db) private void InitProject(SqlSugarClient db) { + db.CodeFirst.InitTables(); + db.CodeFirst.InitTables(); if (db.Queryable().Count() == 0) { @@ -85,11 +89,11 @@ private void InitProject(SqlSugarClient db) { FileSuffix = ".cs", TemplateId1 = _entitytempId + "", - FileModel = "[{ \"name\":\"" + _defaultNamespace + ".Entities\",\"nuget\":[{ \"name\":\"SqlSugarCore\",\"version\":\"5.0.4\" }]}]", + FileModel = "[{ \"name\":\"" + _defaultNamespace + ".Entities\",\"nuget\":[{ \"name\":\"SqlSugarCore\",\"version\":\"5.1.4.108\" }]}]", FileInfo = _net5lib + "", NameFormat = "DbModels\\{0}", ProjentName = "[简单三层]_方案_实体_Sugar", - Path = @"c:\" + _defaultNamespace + @"\Entites", + Path =FileSugar.MergeUrl( @"c:\" + _defaultNamespace + @"\Entites"), IsDeleted = false, IsInit = true, ModelId = 1 @@ -99,29 +103,41 @@ private void InitProject(SqlSugarClient db) FileSuffix = ".cs", NameFormat = "Services\\{0}Manager", TemplateId1 = _biztempId + "", - FileModel = "[{ \"name\":\""+_defaultNamespace+ ".Services\",\"nuget\":[{ \"name\":\"SqlSugarCore\",\"version\":\"5.0.4\" }]},{\"name\":\"Repository\", \"name_space\":\"" + _defaultNamespace+ ".Services\" }]", + FileModel = "[{ \"name\":\""+_defaultNamespace+ ".Services\",\"nuget\":[{ \"name\":\"SqlSugarCore\",\"version\":\"5.1.4.108\" }]},{\"name\":\"Repository\", \"name_space\":\"" + _defaultNamespace+ ".Services\" }]", FileInfo = _net5lib + ","+_dbcontext, ProjentName = "[简单三层]_方案_业务_Sugar", - Path = @"c:\" + _defaultNamespace + @"\Services", + Path = FileSugar.MergeUrl(@"c:\" + _defaultNamespace + @"\Services"), IsDeleted = false, IsInit = true, ModelId = 2, Reference=pid+"" }).ExecuteReturnIdentity(); - db.Insertable(new Project() + var pid3= db.Insertable(new Project() { FileSuffix = ".cs", TemplateId1 = _webtempId + "", - FileModel = "[{ \"name\":\"命名空间\",\"nuget\":[{ \"name\":\"SqlSugarCore\",\"version\":\"5.0.4\" },{ \"name\":\"Microsoft.AspNetCore.Mvc.NewtonsoftJson\",\"version\":\"5.0.10\" },{ \"name\":\"Swashbuckle.AspNetCore\",\"version\":\"5.6.3\" }]},{\"name\":\"Startup\", \"name_space\":\"命名空间\" },{\"name\":\"Program\", \"name_space\":\"命名空间\" },{\"name\":\"appsettings\", \"name_space\":\"命名空间\"}]".Replace("命名空间",$"{_defaultNamespace}.Api"), + FileModel = "[{ \"name\":\"命名空间\",\"nuget\":[{ \"name\":\"SqlSugarCore\",\"version\":\"5.1.4.108\" },{ \"name\":\"Microsoft.AspNetCore.Mvc.NewtonsoftJson\",\"version\":\"5.0.10\" },{ \"name\":\"Swashbuckle.AspNetCore\",\"version\":\"5.6.3\" }]},{\"name\":\"Startup\", \"name_space\":\"命名空间\" },{\"name\":\"Program\", \"name_space\":\"命名空间\" },{\"name\":\"appsettings\", \"name_space\":\"命名空间\"}]".Replace("命名空间",$"{_defaultNamespace}.Api"), FileInfo =string.Join(",",_WebFiles), ProjentName = "[简单三层]_方案_前端_Sugar", NameFormat = "Controllers\\{0}Controller", - Path = @"c:\" + _defaultNamespace + @"\Api", + Path =FileSugar.MergeUrl( @"c:\" + _defaultNamespace + @"\Api"), IsDeleted = false, IsInit = true, ModelId = 3, Reference = pid + ","+pid2 }).ExecuteReturnIdentity(); + + + if (db.Queryable().Count() == 0) + { + db.Insertable(new ProjectGroup() + { + Name = ".Net5 SqlSugar+仓储", + ProjectIds = new int[] { pid, pid2, pid3 }, + SolutionPath =FileSugar.MergeUrl( "c:\\WebFirst\\Demo01"), + ProjectNames=String.Join(",", db.Queryable().In(pid, pid2, pid3).Select(it=>it.ProjentName).ToArray()) + }).ExecuteReturnIdentity(); + } } } @@ -346,8 +362,7 @@ private void InitCodeTable(SqlSugarClient db) Name="byteArray", CSharepType="byte[]", DbType=new DbTypeInfo[]{ - new DbTypeInfo(){ Name="clob"}, - new DbTypeInfo(){ Name="bit"}, + new DbTypeInfo(){ Name="blob"}, new DbTypeInfo(){ Name="longblob"}, new DbTypeInfo(){ Name="binary"} @@ -380,6 +395,131 @@ private void InitCodeTable(SqlSugarClient db) } db.Insertable(list).ExecuteCommand(); } + if (!db.Queryable().Any(it => it.CSharepType == "DateTimeOffset")) + { + db.Insertable(new CodeType() + { + CSharepType= "DateTimeOffset", + Name= "DateTimeOffset", + DbType=new DbTypeInfo[] + { + new DbTypeInfo(){ Name="DateTimeOffset" }, + new DbTypeInfo(){ Name="DateTime" } + } + }).ExecuteCommand(); + } + if (db.Queryable().Any(it => it.Name == "json_default")) + { + db.Updateable().SetColumns(it => new CodeType() { CSharepType = "object" }).Where(it => it.Name == "json_default").ExecuteCommand(); + } + if (!db.Queryable().Any(it => it.Name == "string_char10")) + { + db.Insertable(new CodeType() + { + CSharepType = "string", + Name = "string_char10", + Sort=10000, + DbType = new DbTypeInfo[] + { + new DbTypeInfo(){ Name="char",Length=10 } + } + }).ExecuteCommand(); + } + if (!db.Queryable().Any(it => it.Name == "float")) + { + db.Insertable(new CodeType() + { + CSharepType = "decimal", + Name = "float", + Sort = 10000, + DbType = new DbTypeInfo[] + { + new DbTypeInfo(){ Name="float" } + } + }).ExecuteCommand(); + } + + if (!db.Queryable().Any(it => it.Name == "Extension_Time_20220407")) + { + db.Insertable(new CodeType() + { + CSharepType = "DateTime", + Name = "Extension_Time_20220407", + Sort = 10000, + DbType = new DbTypeInfo[] + { + new DbTypeInfo(){ Name="date" }, + new DbTypeInfo(){ Name="time" }, + new DbTypeInfo(){ Name="timestamp with time zone" }, + new DbTypeInfo(){ Name="timestamptz" }, + new DbTypeInfo(){ Name="timestamp without time zone" }, + new DbTypeInfo(){ Name="time with time zone" } + } + }).ExecuteCommand(); + } + if (!db.Queryable().Any(it => it.Name == "Extension_Bool_20220407")) + { + db.Insertable(new CodeType() + { + CSharepType = "bool", + Name = "Extension_Bool_20220407", + Sort = 10000, + DbType = new DbTypeInfo[] + { + new DbTypeInfo(){ Name="bool" }, + new DbTypeInfo(){ Name="Boolean" } + } + }).ExecuteCommand(); + } + if (!db.Queryable().Any(it => it.Name == "Extension_Decimal_20220407")) + { + db.Insertable(new CodeType() + { + CSharepType = "decimal", + Name = "Extension_Decimal_20220407", + Sort = 10000, + DbType = new DbTypeInfo[] + { + new DbTypeInfo(){ Name="float4" }, + new DbTypeInfo(){ Name="float8" }, + new DbTypeInfo(){ Name="interval" }, + new DbTypeInfo(){ Name="lseg" }, + new DbTypeInfo(){ Name="macaddr" }, + //new DbTypeInfo(){ Name="money" }, + new DbTypeInfo(){ Name="path" }, + new DbTypeInfo(){ Name="point" }, + new DbTypeInfo(){ Name="polygon" }, + new DbTypeInfo(){ Name="double precision" }, + new DbTypeInfo(){ Name="real" } + } + }).ExecuteCommand(); + } + if (!db.Queryable().Any(it => it.Name == "Extension_Byte_20220407")) + { + db.Insertable(new CodeType() + { + CSharepType = "byte", + Name = "Extension_Byte_20220407", + Sort = 10000, + DbType = new DbTypeInfo[] + { + new DbTypeInfo(){ Name="varbit" } + } + }).ExecuteCommand(); + } + if (!db.Queryable().Any(it => it.Name == "Extension_Guid_20220407")) + { + db.Insertable(new CodeType() + { + CSharepType = "guid", + Name = "Extension_Guid_20220407", + Sort = 10000, + DbType = new DbTypeInfo[] + { + new DbTypeInfo(){ Name="uuid" } + } + }).ExecuteCommand(); + } } private void InitConnection(SqlSugarClient db) @@ -680,13 +820,12 @@ private void InitMenu(SqlSugarClient db) Child=new List() { new Menu{ MenuName="配置数据库" , Url="/Database"}, + new Menu{ MenuName="一键生成" , Url="/Solution"}, new Menu{ MenuName="配置实体(类建表模式)" , Url="/CodeFirst"}, new Menu{ MenuName="配置实体(表建类模式)" , Url="/DbFirst"}, new Menu{ MenuName="配置实体(视图建类模式)" , Url="/DbView"}, new Menu{ MenuName="配置业务",Url="/BIZ" }, new Menu{ MenuName="配置前端" ,Url="/Web"}, - new Menu{ MenuName="云方案 ×" , Url="/Solution"}, - } } , diff --git a/SoEasyPlatform/Code/AppStart/Services.cs b/SoEasyPlatform/Code/AppStart/Services.cs index 97900b1a..90e45e4a 100644 --- a/SoEasyPlatform/Code/AppStart/Services.cs +++ b/SoEasyPlatform/Code/AppStart/Services.cs @@ -1,13 +1,8 @@ -using AutoMapper; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -namespace SoEasyPlatform +namespace SoEasyPlatform { public class Services { @@ -18,8 +13,7 @@ public static void AddServices(IServiceCollection services) services.AddAutoMapper(typeof(SoEasyPlatform.MapperProfiles).Assembly); #if DEBUG //启用动态编译 - services.AddControllersWithViews() - .AddRazorRuntimeCompilation(); + services.AddControllersWithViews().AddRazorRuntimeCompilation(); #endif services.AddControllersWithViews().AddNewtonsoftJson(opt => { diff --git a/SoEasyPlatform/Code/Util/FileHelper.cs b/SoEasyPlatform/Code/Util/FileHelper.cs index 0e5da645..f1edf0af 100644 --- a/SoEasyPlatform/Code/Util/FileHelper.cs +++ b/SoEasyPlatform/Code/Util/FileHelper.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; @@ -933,8 +934,13 @@ public static string MergeUrl(params string[] urls) } else if (urls.Length == 1) { + urls = urls.Where(it => it != null).ToArray(); return urls[0]; } + else + { + urls = urls.Where(it => it != null).ToArray(); + } StringBuilder reval = new StringBuilder(); int i = 0; char slash = '\\'; @@ -959,8 +965,43 @@ public static string MergeUrl(params string[] urls) reval.Append(itUrl); itUrl = null; } - return reval.ToString(); - } + return GetRuntimeDirectory(reval.ToString()); + } + #endregion + #region 路径处理 + public static string GetRuntimeDirectory(string path) + { + //ForLinux + if (IsLinuxRunTime()) + return GetLinuxDirectory(path); + //ForWindows + if (IsWindowRunTime()) + return GetWindowDirectory(path); + return path; + } + + //OSPlatform.Windows监测运行环境 + public static bool IsWindowRunTime() + { + return System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + } + + //OSPlatform.Linux运行环境 + public static bool IsLinuxRunTime() + { + return System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + } + + public static string GetLinuxDirectory(string path) + { + string pathTemp = Path.Combine(path); + return pathTemp.Replace("\\", "/"); + } + public static string GetWindowDirectory(string path) + { + string pathTemp = Path.Combine(path); + return pathTemp.Replace("/", "\\"); + } #endregion } } diff --git a/SoEasyPlatform/Code/Util/PubMehtod.cs b/SoEasyPlatform/Code/Util/PubMehtod.cs index 96c4c77b..53ec37da 100644 --- a/SoEasyPlatform/Code/Util/PubMehtod.cs +++ b/SoEasyPlatform/Code/Util/PubMehtod.cs @@ -12,6 +12,7 @@ public static string GetCsharpName(string dbColumnName) if (dbColumnName.Contains("_")) { dbColumnName = dbColumnName.TrimEnd('_'); + dbColumnName = dbColumnName.TrimStart('_'); var array = dbColumnName.Split('_').Select(it=>GetFirstUpper(it,true)).ToArray(); return string.Join("", array); } @@ -31,7 +32,14 @@ private static string GetFirstUpper(string dbColumnName,bool islower=false) } else { - return dbColumnName.Substring(0, 1).ToUpper() + dbColumnName.Substring(1); + if (dbColumnName.ToUpper() == dbColumnName) + { + return dbColumnName.Substring(0, 1).ToUpper() + dbColumnName.Substring(1).ToLower(); + } + else + { + return dbColumnName.Substring(0, 1).ToUpper() + dbColumnName.Substring(1); + } } } } diff --git a/SoEasyPlatform/Code/Util/SyntaxTreeHelper.cs b/SoEasyPlatform/Code/Util/SyntaxTreeHelper.cs index b6459c3c..f6438383 100644 --- a/SoEasyPlatform/Code/Util/SyntaxTreeHelper.cs +++ b/SoEasyPlatform/Code/Util/SyntaxTreeHelper.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Reflection; using System.Runtime.Loader; +using System.Text.RegularExpressions; using System.Threading.Tasks; namespace SoEasyPlatform @@ -15,6 +16,11 @@ public class SyntaxTreeHelper { public static Type GetModelTypeByClass(string classString, string typeName) { + var typeFirstChar = typeName.FirstOrDefault() + ""; + if (Regex.IsMatch(typeFirstChar,@"^\d$")) + { + throw new Exception("类的首字母不能是数字"); + } //Write("Parsing the code into the SyntaxTree"); SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(classString); @@ -51,11 +57,12 @@ public static Type GetModelTypeByClass(string classString, string typeName) diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error); + string message = ""; foreach (Diagnostic diagnostic in failures) { - Console.Error.WriteLine("\t{0}: {1}", diagnostic.Id, diagnostic.GetMessage()); + message += diagnostic.GetMessage(); } - throw new Exception("解析实体类出错,请检查命名" + classString); + throw new Exception("解析实体类出错,请检查命名" + message +" \r\n "+classString); } else { diff --git a/SoEasyPlatform/Code/Util/Table_ToExcel.cs b/SoEasyPlatform/Code/Util/Table_ToExcel.cs index 7c73e3f0..236712b4 100644 --- a/SoEasyPlatform/Code/Util/Table_ToExcel.cs +++ b/SoEasyPlatform/Code/Util/Table_ToExcel.cs @@ -21,8 +21,10 @@ public static byte[] ExportExcel(DataTable[] dts, string name, int[] widths = nu { XLWorkbook wb = new XLWorkbook(); + int index = 0; foreach (var dt in dts) { + index++; for (int i = 1; i < 15; i++) { //删除Ignore列 @@ -46,7 +48,21 @@ public static byte[] ExportExcel(DataTable[] dts, string name, int[] widths = nu } newdt.Rows.Add(dr); } - wb.Worksheets.Add(newdt, dt.TableName); + try + { + wb.Worksheets.Add(newdt, dt.TableName); + } + catch + { + if (dt.TableName.Length < 28) + { + wb.Worksheets.Add(newdt,"_"+dt.TableName); + } + else + { + wb.Worksheets.Add(newdt, dt.TableName.Substring(0, 25) + DateTime.Now.ToString("...") + index); + } + } var worksheet = wb.Worksheets.Last(); foreach (var item in worksheet.Tables) { diff --git a/SoEasyPlatform/Code/Util/ZipHelper.cs b/SoEasyPlatform/Code/Util/ZipHelper.cs new file mode 100644 index 00000000..9947584c --- /dev/null +++ b/SoEasyPlatform/Code/Util/ZipHelper.cs @@ -0,0 +1,397 @@ +/*** +* Title:"基础工具" 项目 +* Title:"基础工具" 项目 +* 主题:压缩包帮助类 +* Description: +* 功能: +* 1、压缩单个文件 +* 2、压缩多个文件 +* 3、压缩多层目录 +* 4、递归遍历目录 +* 5、解压缩一个 zip 文件 +* 6、获取压缩文件中指定类型的文件 +* 7、获取压缩文件中的所有文件 +* Date:2021 +* Version:0.1版本 +* Author:Coffee +* Modify Recoder: +*/ + +using ICSharpCode.SharpZipLib.Zip; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace SoEasyPlatform +{ + public class ZipHelper + { + /// + /// 压缩单个文件 + /// + /// 要压缩的文件 + /// 压缩后的文件 + /// 压缩等级 + /// 每次写入大小 + public static void ZipFile(string fileToZip, string zipedFile, int compressionLevel, int blockSize) + { + //如果文件没有找到,则报错 + if (!File.Exists(fileToZip)) + { + throw new FileNotFoundException("指定要压缩的文件: " + fileToZip + " 不存在!"); + } + + using (FileStream ZipFile = File.Create(zipedFile)) + { + using (ZipOutputStream ZipStream = new ZipOutputStream(ZipFile)) + { + using (FileStream StreamToZip = new FileStream(fileToZip, FileMode.Open, FileAccess.Read)) + { + string fileName = fileToZip.Substring(fileToZip.LastIndexOf("\\") + 1); + + ZipEntry ZipEntry = new ZipEntry(fileName); + + ZipStream.PutNextEntry(ZipEntry); + + ZipStream.SetLevel(compressionLevel); + + byte[] buffer = new byte[blockSize]; + + int sizeRead = 0; + + try + { + do + { + sizeRead = StreamToZip.Read(buffer, 0, buffer.Length); + ZipStream.Write(buffer, 0, sizeRead); + } + while (sizeRead > 0); + } + catch + { + + } + + StreamToZip.Close(); + } + + ZipStream.Finish(); + ZipStream.Close(); + } + + ZipFile.Close(); + } + } + + /// + /// 压缩单个文件 + /// + /// 要进行压缩的文件名 + /// 压缩后生成的压缩文件名 + public static void ZipFile(string fileToZip, string zipedFile) + { + //如果文件没有找到,则报错 + if (!File.Exists(fileToZip)) + { + throw new FileNotFoundException("指定要压缩的文件: " + fileToZip + " 不存在!"); + } + + using (FileStream fs = File.OpenRead(fileToZip)) + { + byte[] buffer = new byte[fs.Length]; + fs.Read(buffer, 0, buffer.Length); + fs.Close(); + + using (FileStream ZipFile = File.Create(zipedFile)) + { + using (ZipOutputStream ZipStream = new ZipOutputStream(ZipFile)) + { + string fileName = fileToZip.Substring(fileToZip.LastIndexOf("\\") + 1); + ZipEntry ZipEntry = new ZipEntry(fileName); + ZipStream.PutNextEntry(ZipEntry); + ZipStream.SetLevel(5); + + ZipStream.Write(buffer, 0, buffer.Length); + ZipStream.Finish(); + ZipStream.Close(); + } + } + } + } + + /// + /// 压缩多个文件到指定路径 + /// + /// 压缩到哪个路径 + /// 压缩文件名称 + public static void ZipFile(List sourceFileNames, string zipFileName) + { + //压缩文件打包 + using (ZipOutputStream s = new ZipOutputStream(File.Create(zipFileName))) + { + s.SetLevel(9); + byte[] buffer = new byte[4096]; + foreach (string file in sourceFileNames) + { + if (Directory.Exists(file))// 先当作目录处理如果存在这个目录就递归Copy该目录下面的文件 + { + string pPath = ""; + pPath += Path.GetFileName(file); + pPath += "\\"; + ZipSetp(file, s, pPath, sourceFileNames); + } + else // 否则直接压缩文件 + { + + ZipEntry entry = new ZipEntry(Path.GetFileName(file)); + entry.DateTime = DateTime.Now; + s.PutNextEntry(entry); + using (FileStream fs = File.OpenRead(file)) + { + int sourceBytes; + do + { + sourceBytes = fs.Read(buffer, 0, buffer.Length); + s.Write(buffer, 0, sourceBytes); + } while (sourceBytes > 0); + } + } + } + s.Finish(); + s.Close(); + } + } + + + /// + /// 压缩多层目录 + /// + /// 待压缩目录 + /// 压缩后生成的压缩文件名,绝对路径 + public static void ZipFileDirectory(string strDirectory, string zipedFile) + { + using (FileStream ZipFile = File.Create(zipedFile)) + { + using (ZipOutputStream s = new ZipOutputStream(ZipFile)) + { + s.SetLevel(9); + ZipSetp(strDirectory, s, ""); + } + } + } + + /// + /// 压缩多层目录 + /// + /// 待压缩目录 + /// 压缩后生成的压缩文件名,绝对路径 + /// 指定要压缩的文件列表(完全路径) + public static void ZipFileDirectory(string strDirectory, string zipedFile, List files) + { + using (FileStream ZipFile = File.Create(zipedFile)) + { + using (ZipOutputStream s = new ZipOutputStream(ZipFile)) + { + s.SetLevel(9); + ZipSetp(strDirectory, s, "", files); + } + } + } + + /// + /// 递归遍历目录 + /// + /// 需遍历的目录 + /// 压缩输出流对象 + /// The parent path. + /// 需要压缩的文件 + private static void ZipSetp(string strDirectory, ZipOutputStream s, string parentPath, List files = null!) + { + if (strDirectory[strDirectory.Length - 1] != Path.DirectorySeparatorChar) + { + strDirectory += Path.DirectorySeparatorChar; + } + + string[] filenames = Directory.GetFileSystemEntries(strDirectory); + + byte[] buffer = new byte[4096]; + foreach (string file in filenames)// 遍历所有的文件和目录 + { + if (files != null && !files.Contains(file)) + { + continue; + } + if (Directory.Exists(file))// 先当作目录处理如果存在这个目录就递归Copy该目录下面的文件 + { + string pPath = parentPath; + pPath += Path.GetFileName(file); + pPath += "\\"; + ZipSetp(file, s, pPath, files!); + } + else // 否则直接压缩文件 + { + //打开压缩文件 + string fileName = parentPath + Path.GetFileName(file); + ZipEntry entry = new ZipEntry(fileName); + + entry.DateTime = DateTime.Now; + + s.PutNextEntry(entry); + using (FileStream fs = File.OpenRead(file)) + { + int sourceBytes; + do + { + sourceBytes = fs.Read(buffer, 0, buffer.Length); + s.Write(buffer, 0, sourceBytes); + } while (sourceBytes > 0); + + } + } + } + } + + /// + /// 解压缩一个 zip 文件。 + /// + /// 压缩文件 + /// 解压目录 + /// zip 文件的密码。 + /// 是否覆盖已存在的文件。 + public static void UnZip(string zipedFile, string strDirectory, bool overWrite, string password) + { + + if (strDirectory == "") + strDirectory = Directory.GetCurrentDirectory(); + if (!strDirectory.EndsWith("\\")) + strDirectory = strDirectory + "\\"; + + using (ZipInputStream s = new ZipInputStream(File.OpenRead(zipedFile))) + { + if (password != null) + { + s.Password = password; + } + ZipEntry theEntry; + + while ((theEntry = s.GetNextEntry()) != null) + { + string directoryName = ""; + string pathToZip = ""; + pathToZip = theEntry.Name; + + if (pathToZip != "") + directoryName = Path.GetDirectoryName(pathToZip) + "\\"; + + string fileName = Path.GetFileName(pathToZip); + + Directory.CreateDirectory(strDirectory + directoryName); + + if (fileName != "") + { + if (File.Exists(strDirectory + directoryName + fileName) && overWrite || !File.Exists(strDirectory + directoryName + fileName)) + { + using (FileStream streamWriter = File.Create(strDirectory + directoryName + fileName)) + { + int size = 2048; + byte[] data = new byte[2048]; + while (true) + { + size = s.Read(data, 0, data.Length); + + if (size > 0) + streamWriter.Write(data, 0, size); + else + break; + } + streamWriter.Close(); + } + } + } + } + + s.Close(); + } + } + + /// + /// 解压缩一个 zip 文件。 + /// + /// 压缩文件 + /// 解压目录 + /// 是否覆盖已存在的文件。 + public static void UnZip(string zipedFile, string strDirectory, bool overWrite) + { + UnZip(zipedFile, strDirectory, overWrite, null!); + } + + /// + /// 解压缩一个 zip 文件。 + /// 覆盖已存在的文件。 + /// + /// 压缩文件 + /// 解压目录 + public static void UnZip(string zipedFile, string strDirectory) + { + UnZip(zipedFile, strDirectory, true); + } + + /// + /// 获取压缩文件中指定类型的文件 + /// + /// 压缩文件 + /// 文件类型(.txt|.exe) + /// 文件名称列表(包含子目录) + public static List GetFiles(string zipedFile, List fileExtension) + { + List files = new List(); + if (!File.Exists(zipedFile)) + { + //return files; + throw new FileNotFoundException(zipedFile); + } + + using (ZipInputStream s = new ZipInputStream(File.OpenRead(zipedFile))) + { + ZipEntry theEntry; + while ((theEntry = s.GetNextEntry()) != null) + { + if (theEntry.IsFile) + { + //Console.WriteLine("Name : {0}", theEntry.Name); + if (fileExtension != null) + { + if (fileExtension.Contains(Path.GetExtension(theEntry.Name))) + { + files.Add(theEntry.Name); + } + } + else + { + files.Add(theEntry.Name); + } + } + } + s.Close(); + } + + return files; + } + + /// + /// 获取压缩文件中的所有文件 + /// + /// 压缩文件 + /// 文件名称列表(包含子目录) + public static List GetFiles(string zipedFile) + { + return GetFiles(zipedFile, null!); + } + + + + }//Class_end + +} \ No newline at end of file diff --git a/SoEasyPlatform/InitProjects/1_Main.cs b/SoEasyPlatform/InitProjects/1_Main.cs new file mode 100644 index 00000000..d6551110 --- /dev/null +++ b/SoEasyPlatform/InitProjects/1_Main.cs @@ -0,0 +1,41 @@ +using Newtonsoft.Json.Linq; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml.Linq; + +namespace SoEasyPlatform +{ + /// + /// 用来初始化整个项目主入口 + /// + public partial class InitTable + { + SqlSugarClient db; + private void InitProjects(SqlSugarClient db) + { + this.db = db; + var directory = FileSugar.MergeUrl(Directory.GetCurrentDirectory(), "wwwroot", "template", "Projects"); + if (!Directory.Exists(directory)) Directory.CreateDirectory(directory); + var slnListPathList = Directory.GetDirectories(directory); + if (slnListPathList == null) return; + try + { + db.BeginTran(); + db.Updateable().SetColumns(it => it.Description == "") +.Where(it => true) +.ExecuteCommand(); + foreach (var sln in slnListPathList) + { + AddSln(sln); + } + db.CommitTran(); + } + catch (System.Exception ex) + { + db.RollbackTran(); + } + } + } +} diff --git a/SoEasyPlatform/InitProjects/2_SlnManager.cs b/SoEasyPlatform/InitProjects/2_SlnManager.cs new file mode 100644 index 00000000..93edf3b2 --- /dev/null +++ b/SoEasyPlatform/InitProjects/2_SlnManager.cs @@ -0,0 +1,76 @@ +using SqlSugar; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Linq; + +namespace SoEasyPlatform +{ + /// + ///项目解决方案管理 + /// + public partial class InitTable + { + int groupId = 0; + private void AddSln(string sln) + { + projectNames = ""; + var slnName = System.IO.Path.GetFileName(sln); + var groupdata = db.Queryable().First(it => it.Name == slnName); + ClearGroup(groupdata); + groupdata = groupdata==null?CreateEmptyProject():groupdata; + if (groupdata.Id == 0) + { + groupId = db.Insertable(groupdata).ExecuteReturnIdentity(); + } + else + { + groupId = groupdata.Id; + } + var ids = AddProjects(sln, slnName); + UpdateProjectGroup(slnName, ids); + } + + private ProjectGroup UpdateProjectGroup(string slnName, List ids) + { + ProjectGroup projectGroup = new ProjectGroup() + { + ProjectIds = ids.ToArray(), + Name = slnName, + ProjectNames = projectNames.TrimEnd(','), + SolutionPath =FileSugar.MergeUrl("c:\\Projects\\" + slnName), + Sort = 100, + Id = groupId, + Description= $"启用文件同步中,点击关闭" + }; + + db.Updateable(projectGroup).ExecuteCommand(); + return projectGroup; + } + + private static ProjectGroup CreateEmptyProject() + { + return new ProjectGroup() + { + ProjectIds = new int[] { }, + Name = "", + ProjectNames = "", + SolutionPath = "", + Sort = 100 + }; + } + + private void ClearGroup(ProjectGroup groupdata) + { + if (groupdata != null) + { + + //db.Deleteable(groupdata).ExecuteCommand(); + db.Deleteable().Where(it => it.SolutionId.Equals(groupdata.Id)).ExecuteCommand(); + db.Deleteable().Where(it => it.SolutionId.Equals(groupdata.Id)).ExecuteCommand(); + db.Deleteable