From 451b6c9769577f8c37561737cf18401f3e8ca0de Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Fri, 31 May 2019 20:30:09 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E5=A2=9E=E5=8A=A0=20NavigateAttribute=20?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=AF=BC=E8=88=AA=E5=85=B3=E7=B3=BB=EF=BC=9B?= =?UTF-8?q?=20-=20=E4=BF=AE=E5=A4=8D=20LinqToSql=20=E6=96=B9=E6=B3=95?= =?UTF-8?q?=EF=BC=8C=E5=BC=80=E5=90=AF=E8=87=AA=E5=8A=A8=E8=BF=81=E7=A7=BB?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E8=BF=81=E7=A7=BB=E4=BA=86=E6=97=A0=E5=85=B3?= =?UTF-8?q?=E7=B1=BB=E7=9A=84=20bug=EF=BC=9B=20-=20=E4=BF=AE=E5=A4=8D=20Or?= =?UTF-8?q?acle=20DbFirst=20date(7)=20=E7=B1=BB=E5=9E=8B=E6=9C=AA=E5=A4=84?= =?UTF-8?q?=E7=90=86=E7=9A=84=20bug=EF=BC=9B#57=20-=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=20AsSelect().Any()=20=E6=9C=AA=E7=BB=99=E5=85=B6=E4=BB=96?= =?UTF-8?q?=E6=9D=A1=E4=BB=B6=E6=97=B6=EF=BC=8C=E4=BA=A7=E7=94=9F=20null?= =?UTF-8?q?=20bug=EF=BC=9B=20-=20=E5=A2=9E=E5=8A=A0=20FreeSql.Extensions.L?= =?UTF-8?q?azyLoading=20=E5=AF=B9=20.net=204.5=20=E7=9A=84=E6=94=AF?= =?UTF-8?q?=E6=8C=81=EF=BC=9B=20-=20=E4=BC=98=E5=8C=96=20MySql=20CodeFirst?= =?UTF-8?q?=20=E5=A2=9E=E5=8A=A0=20DateTime=20=E8=BF=81=E7=A7=BB=E5=90=8E?= =?UTF-8?q?=EF=BC=8C=E9=BB=98=E8=AE=A4=E5=80=BC=E4=B8=BA=200000-00-00=20?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E8=AF=BB=E5=8F=96=E5=A4=B1=E8=B4=A5=E7=9A=84?= =?UTF-8?q?=20bug=EF=BC=9B=20-=20=E4=BC=98=E5=8C=96=20LazyLoading=20?= =?UTF-8?q?=E5=8F=8B=E5=A5=BD=E9=94=99=E8=AF=AF=E6=8F=90=E7=A4=BA=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FreeSql.Extensions.LazyLoading.csproj | 10 +- .../LazyLoadingComplier.cs | 28 ++- FreeSql.Tests/FreeSql.Tests.csproj | 2 +- FreeSql.Tests/UnitTest1.cs | 67 +++++++ FreeSql.sln | 30 ++- FreeSql/DataAnnotations/ColumnAttribute.cs | 2 +- FreeSql/DataAnnotations/NavigateAttribute.cs | 16 ++ FreeSql/Extensions/EntityUtilExtensions.cs | 19 +- FreeSql/FreeSql.csproj | 2 +- FreeSql/FreeSql.xml | 10 +- FreeSql/Internal/CommonExpression.cs | 6 +- .../CommonProvider/CodeFirstProvider.cs | 75 +++++++ .../SelectProvider/Select1Provider.cs | 4 + FreeSql/Internal/UtilsExpressionTree.cs | 184 +++++++++++------- .../FreeSql.Provider.MySql.csproj | 2 +- .../FreeSql.Provider.MySql/MySqlCodeFirst.cs | 58 +----- .../FreeSql.Provider.MySqlConnector.csproj | 2 +- .../FreeSql.Provider.Oracle.csproj | 2 +- .../OracleCodeFirst.cs | 57 +----- .../FreeSql.Provider.Oracle/OracleDbFirst.cs | 4 + .../FreeSql.Provider.PostgreSQL.csproj | 2 +- .../PostgreSQLCodeFirst.cs | 59 +----- .../FreeSql.Provider.SqlServer.csproj | 2 +- .../SqlServerCodeFirst.cs | 62 +----- .../FreeSql.Provider.Sqlite.csproj | 2 +- .../SqliteCodeFirst.cs | 59 +----- readme.md | 2 +- 27 files changed, 407 insertions(+), 361 deletions(-) create mode 100644 FreeSql/DataAnnotations/NavigateAttribute.cs create mode 100644 FreeSql/Internal/CommonProvider/CodeFirstProvider.cs diff --git a/Extensions/FreeSql.Extensions.LazyLoading/FreeSql.Extensions.LazyLoading.csproj b/Extensions/FreeSql.Extensions.LazyLoading/FreeSql.Extensions.LazyLoading.csproj index ae2caae1..dea41cf0 100644 --- a/Extensions/FreeSql.Extensions.LazyLoading/FreeSql.Extensions.LazyLoading.csproj +++ b/Extensions/FreeSql.Extensions.LazyLoading/FreeSql.Extensions.LazyLoading.csproj @@ -1,8 +1,8 @@  - netstandard2.0 - 0.6.3 + netstandard2.0;net45 + 0.6.4 true YeXiangQin FreeSql 扩展包,可实现【延时加载】属性. @@ -17,9 +17,13 @@ true - + + + + ns20;netstandard20 + diff --git a/Extensions/FreeSql.Extensions.LazyLoading/LazyLoadingComplier.cs b/Extensions/FreeSql.Extensions.LazyLoading/LazyLoadingComplier.cs index 9c50116a..90ebbd32 100644 --- a/Extensions/FreeSql.Extensions.LazyLoading/LazyLoadingComplier.cs +++ b/Extensions/FreeSql.Extensions.LazyLoading/LazyLoadingComplier.cs @@ -1,4 +1,6 @@ -using System; +using Microsoft.CSharp; +using System; +using System.CodeDom.Compiler; using System.Collections.Generic; using System.Reflection; using System.Text; @@ -7,6 +9,7 @@ namespace FreeSql.Extensions.LazyLoading { public class LazyLoadingComplier { +#if ns20 internal static Lazy _compiler = new Lazy(() => { //var dlls = Directory.GetFiles(Directory.GetParent(Type.GetType("IFreeSql, FreeSql").Assembly.Location).FullName, "*.dll"); var compiler = new CSScriptLib.RoslynEvaluator(); @@ -26,5 +29,28 @@ namespace FreeSql.Extensions.LazyLoading { public static Assembly CompileCode(string cscode) { return _compiler.Value.CompileCode(cscode); } +#else + + + public static Assembly CompileCode(string cscode) { + + using (var compiler = CodeDomProvider.CreateProvider("cs")) { + + var objCompilerParameters = new CompilerParameters(); + objCompilerParameters.ReferencedAssemblies.Add("System.dll"); + objCompilerParameters.ReferencedAssemblies.Add("FreeSql.dll"); + objCompilerParameters.GenerateExecutable = false; + objCompilerParameters.GenerateInMemory = true; + + CompilerResults cr = compiler.CompileAssemblyFromSource(objCompilerParameters, cscode); + + if (cr.Errors.Count > 0) + throw new Exception(cr.Errors[0].ErrorText); + + return cr.CompiledAssembly; + } + } + +#endif } } diff --git a/FreeSql.Tests/FreeSql.Tests.csproj b/FreeSql.Tests/FreeSql.Tests.csproj index 4157ec50..b778f4e2 100644 --- a/FreeSql.Tests/FreeSql.Tests.csproj +++ b/FreeSql.Tests/FreeSql.Tests.csproj @@ -7,7 +7,6 @@ - @@ -15,6 +14,7 @@ + diff --git a/FreeSql.Tests/UnitTest1.cs b/FreeSql.Tests/UnitTest1.cs index f9c9e131..2c7c220c 100644 --- a/FreeSql.Tests/UnitTest1.cs +++ b/FreeSql.Tests/UnitTest1.cs @@ -210,10 +210,72 @@ namespace FreeSql.Tests { [Column(Name = "release_time")] public int ReleaseTime { get; set; } + public DateTime testaddtime { get; set; } + public DateTime? testaddtime2 { get; set; } + } + + public class NewsArticleDto : NewsArticle { + + } + + + public class TaskBuildInfo { + [FreeSql.DataAnnotations.Column(IsPrimary = true)] + public Guid Id { get; set; } + public Guid TbId { get; set; } + public Guid DataBaseConfigId { get; set; } + public string Name { get; set; } + public int Level { get; set; } + + [Column(IsIgnore = true)] + public virtual TaskBuild TaskBuild { get; set; } + } + public class Templates { + [Column(IsPrimary = true)] + public Guid Id { get; set; } + public string Title { get; set; } + public DateTime AddTime { get; set; } = DateTime.Now; + public DateTime EditTime { get; set; } + [Column(DbType = "text")] + public string Code { get; set; } + } + public class TaskBuild { + + [FreeSql.DataAnnotations.Column(IsPrimary = true)] + public Guid Id { get; set; } + public string TaskName { get; set; } + public Guid TemplatesId { get; set; } + public string GeneratePath { get; set; } + public string FileName { get; set; } + public string NamespaceName { get; set; } + public bool OptionsEntity01 { get; set; } = false; + public bool OptionsEntity02 { get; set; } = false; + public bool OptionsEntity03 { get; set; } = false; + public bool OptionsEntity04 { get; set; } = false; + + [Navigate("TbId")] + public virtual ICollection Builds { get; set; } + public Templates Templates { get; set; } } [Fact] public void Test1() { + g.sqlite.SetDbContextOptions(opt => opt.EnableAddOrUpdateNavigateList = true); + var trepo = g.sqlite.GetGuidRepository(); + trepo.Insert(new TaskBuild { + TaskName = "tt11", + Builds = new[] { + new TaskBuildInfo { + Level = 1, + Name = "t111_11" + } + } + }); + + var ttdkdkd = trepo.Select.Where(a => a.Builds.AsSelect().Any()).ToList(); + + var list1113233 = trepo.Select.ToList(); + var entity = new NewsArticle { ArticleId = 1, @@ -223,11 +285,16 @@ namespace FreeSql.Tests { ArticleId = 1, ChannelId = 1, }; + + g.mysql.Insert(new[] { entity }).ExecuteAffrows(); + var sqldddkdk = g.mysql.Update(where) .SetSource(entity) .UpdateColumns(x => new { x.Status, x.CategoryId, x.ArticleTitle }) .ToSql(); + var sqldddklist = g.mysql.Select().Select(a => new NewsArticleDto { }).ToList(); + var sql1111333 = g.mysql.Update() .SetSource(new Model2 { id = 1, Title = "xxx", Parent_id = 0 }) diff --git a/FreeSql.sln b/FreeSql.sln index 024df11f..912afefe 100644 --- a/FreeSql.sln +++ b/FreeSql.sln @@ -40,7 +40,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Extensions.LazyLoading", "Extensions\FreeSql.Extensions.LazyLoading\FreeSql.Extensions.LazyLoading.csproj", "{1FE00D5E-EC0F-4238-93EC-DABA26DBD1A9}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FreeSql.Provider.MySqlConnector", "Providers\FreeSql.Provider.MySqlConnector\FreeSql.Provider.MySqlConnector.csproj", "{D2A41321-5E84-410B-B25C-3AA122D4CA27}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Provider.MySqlConnector", "Providers\FreeSql.Provider.MySqlConnector\FreeSql.Provider.MySqlConnector.csproj", "{D2A41321-5E84-410B-B25C-3AA122D4CA27}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.DbContext", "..\FreeSql.DbContext\FreeSql.DbContext\FreeSql.DbContext.csproj", "{9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Repository", "..\FreeSql.DbContext\FreeSql.Repository\FreeSql.Repository.csproj", "{D7A9C833-8679-41B3-8258-757A6FB27A0E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -220,6 +224,30 @@ Global {D2A41321-5E84-410B-B25C-3AA122D4CA27}.Release|x64.Build.0 = Release|Any CPU {D2A41321-5E84-410B-B25C-3AA122D4CA27}.Release|x86.ActiveCfg = Release|Any CPU {D2A41321-5E84-410B-B25C-3AA122D4CA27}.Release|x86.Build.0 = Release|Any CPU + {9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Debug|x64.ActiveCfg = Debug|Any CPU + {9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Debug|x64.Build.0 = Debug|Any CPU + {9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Debug|x86.ActiveCfg = Debug|Any CPU + {9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Debug|x86.Build.0 = Debug|Any CPU + {9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Release|Any CPU.Build.0 = Release|Any CPU + {9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Release|x64.ActiveCfg = Release|Any CPU + {9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Release|x64.Build.0 = Release|Any CPU + {9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Release|x86.ActiveCfg = Release|Any CPU + {9A04925D-4EBA-4B4D-A6DA-F79A41F0F14E}.Release|x86.Build.0 = Release|Any CPU + {D7A9C833-8679-41B3-8258-757A6FB27A0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D7A9C833-8679-41B3-8258-757A6FB27A0E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D7A9C833-8679-41B3-8258-757A6FB27A0E}.Debug|x64.ActiveCfg = Debug|Any CPU + {D7A9C833-8679-41B3-8258-757A6FB27A0E}.Debug|x64.Build.0 = Debug|Any CPU + {D7A9C833-8679-41B3-8258-757A6FB27A0E}.Debug|x86.ActiveCfg = Debug|Any CPU + {D7A9C833-8679-41B3-8258-757A6FB27A0E}.Debug|x86.Build.0 = Debug|Any CPU + {D7A9C833-8679-41B3-8258-757A6FB27A0E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D7A9C833-8679-41B3-8258-757A6FB27A0E}.Release|Any CPU.Build.0 = Release|Any CPU + {D7A9C833-8679-41B3-8258-757A6FB27A0E}.Release|x64.ActiveCfg = Release|Any CPU + {D7A9C833-8679-41B3-8258-757A6FB27A0E}.Release|x64.Build.0 = Release|Any CPU + {D7A9C833-8679-41B3-8258-757A6FB27A0E}.Release|x86.ActiveCfg = Release|Any CPU + {D7A9C833-8679-41B3-8258-757A6FB27A0E}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/FreeSql/DataAnnotations/ColumnAttribute.cs b/FreeSql/DataAnnotations/ColumnAttribute.cs index 4bc8dedb..412b3bde 100644 --- a/FreeSql/DataAnnotations/ColumnAttribute.cs +++ b/FreeSql/DataAnnotations/ColumnAttribute.cs @@ -66,7 +66,7 @@ namespace FreeSql.DataAnnotations { /// /// 数据库默认值 /// - public object DbDefautValue { get; set; } + public object DbDefautValue { get; internal set; } /// /// 类型映射,比如:可将 enum 属性映射成 typeof(string) diff --git a/FreeSql/DataAnnotations/NavigateAttribute.cs b/FreeSql/DataAnnotations/NavigateAttribute.cs new file mode 100644 index 00000000..d9b052f5 --- /dev/null +++ b/FreeSql/DataAnnotations/NavigateAttribute.cs @@ -0,0 +1,16 @@ +using System; +using System.Linq; + +namespace FreeSql.DataAnnotations { + public class NavigateAttribute : Attribute { + + /// + /// 导航属性,手工绑定 + /// + public string Bind { get; set; } + + public NavigateAttribute(string bind) { + this.Bind = bind; + } + } +} diff --git a/FreeSql/Extensions/EntityUtilExtensions.cs b/FreeSql/Extensions/EntityUtilExtensions.cs index 30ef1a80..f7bb3f2d 100644 --- a/FreeSql/Extensions/EntityUtilExtensions.cs +++ b/FreeSql/Extensions/EntityUtilExtensions.cs @@ -15,24 +15,26 @@ namespace FreeSql.Extensions.EntityUtil { static readonly MethodInfo MethodStringConcat = typeof(string).GetMethod("Concat", new Type[] { typeof(object) }); static readonly MethodInfo MethodFreeUtilNewMongodbId = typeof(FreeUtil).GetMethod("NewMongodbId"); - static ConcurrentDictionary>> _dicGetEntityKeyString = new ConcurrentDictionary>>(); + static ConcurrentDictionary>> _dicGetEntityKeyString = new ConcurrentDictionary>>(); /// - /// 获取实体的主键值,以 "*|_,[,_|*" 分割,当任意一个主键属性无值时(当Guid无值时,会生成有序的新值),返回 null + /// 获取实体的主键值,以 "*|_,[,_|*" 分割,当任意一个主键属性无值时,返回 null /// /// /// /// + /// 当Guid无值时,会生成有序的新值 /// /// //public static string GetEntityKeyString(this IFreeSql orm, TEntity entity, string splitString = "*|_,[,_|*") => GetEntityKeyString(orm, typeof(TEntity), entity, splitString); - public static string GetEntityKeyString(this IFreeSql orm, Type entityType, object entity, string splitString = "*|_,[,_|*") { + public static string GetEntityKeyString(this IFreeSql orm, Type entityType, object entity, bool genGuid, string splitString = "*|_,[,_|*") { if (entity == null) return null; if (entityType == null) entityType = entity.GetType(); - var func = _dicGetEntityKeyString.GetOrAdd(orm.Ado.DataType, dt => new ConcurrentDictionary>()).GetOrAdd(entityType, t => { + var func = _dicGetEntityKeyString.GetOrAdd(orm.Ado.DataType, dt => new ConcurrentDictionary>()).GetOrAdd(entityType, t => { var _table = orm.CodeFirst.GetTableByEntity(t); var pks = _table.Primarys; var returnTarget = Expression.Label(typeof(string)); var parm1 = Expression.Parameter(typeof(object)); + var parm2 = Expression.Parameter(typeof(bool)); var var1Parm = Expression.Variable(t); var var2Sb = Expression.Variable(typeof(StringBuilder)); var var3IsNull = Expression.Variable(typeof(bool)); @@ -84,7 +86,10 @@ namespace FreeSql.Extensions.EntityUtil { Expression.IsFalse(var3IsNull), Expression.IfThenElse( Expression.Equal(Expression.MakeMemberAccess(var1Parm, _table.Properties[pks[a].CsName]), Expression.Default(pks[a].CsType)), - expthen, + Expression.IfThen( + Expression.IsTrue(parm2), + expthen + ), Expression.Block( new Expression[]{ a > 0 ? Expression.Call(var2Sb, MethodStringBuilderAppend, Expression.Constant(splitString)) : null, @@ -119,9 +124,9 @@ namespace FreeSql.Extensions.EntityUtil { ) ); exps.Add(Expression.Label(returnTarget, Expression.Default(typeof(string)))); - return Expression.Lambda>(Expression.Block(new[] { var1Parm, var2Sb, var3IsNull }, exps), new[] { parm1 }).Compile(); + return Expression.Lambda>(Expression.Block(new[] { var1Parm, var2Sb, var3IsNull }, exps), new[] { parm1, parm2 }).Compile(); }); - return func(entity); + return func(entity, genGuid); } static ConcurrentDictionary>> _dicGetEntityKeyValues = new ConcurrentDictionary>>(); /// diff --git a/FreeSql/FreeSql.csproj b/FreeSql/FreeSql.csproj index ab936e84..b8b8c8e1 100644 --- a/FreeSql/FreeSql.csproj +++ b/FreeSql/FreeSql.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45 - 0.6.3 + 0.6.4 true YeXiangQin FreeSql is the most convenient ORM in dotnet. It supports Mysql, Postgresql, SqlServer, Oracle and Sqlite. diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index cca0ec01..dcb10d9c 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -113,6 +113,11 @@ + + + 导航属性,手工绑定 + + 数据库表名 @@ -288,13 +293,14 @@ 枚举项 - + - 获取实体的主键值,以 "*|_,[,_|*" 分割,当任意一个主键属性无值时(当Guid无值时,会生成有序的新值),返回 null + 获取实体的主键值,以 "*|_,[,_|*" 分割,当任意一个主键属性无值时,返回 null + 当Guid无值时,会生成有序的新值 diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index 69b4fd57..7c1fe876 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -500,7 +500,7 @@ namespace FreeSql.Internal { if (asSelectParentExp != null) { var testExecuteExp = asSelectParentExp; if (asSelectParentExp.NodeType == ExpressionType.Parameter) //执行leftjoin关联 - testExecuteExp = Expression.Property(testExecuteExp, _common.GetTableByEntity(asSelectParentExp.Type).Properties.First().Value); + testExecuteExp = Expression.Property(testExecuteExp, _common.GetTableByEntity(asSelectParentExp.Type).ColumnsByCs.First().Key); var tsc2 = tsc.CloneSetgetSelectGroupingMapStringAndgetSelectGroupingMapStringAndtbtype(new List(), tsc.getSelectGroupingMapString, SelectTableInfoType.LeftJoin); tsc2.isDisableDiyParse = true; tsc2.style = ExpressionStyle.AsSelect; @@ -553,6 +553,10 @@ namespace FreeSql.Internal { } if (fsql != null) { if (asSelectParentExp != null) { //执行 asSelect() 的关联,OneToMany,ManyToMany + if (fsqltables[0].Parameter == null) { + fsqltables[0].Alias = $"tb_{fsqltables.Count}"; + fsqltables[0].Parameter = Expression.Parameter(asSelectEntityType, fsqltables[0].Alias); + } var fsqlWhere = _dicExpressionLambdaToSqlAsSelectWhereMethodInfo.GetOrAdd(asSelectEntityType, asSelectEntityType3 => typeof(ISelect<>).MakeGenericType(asSelectEntityType3).GetMethod("Where", new[] { typeof(Expression<>).MakeGenericType(typeof(Func<,>).MakeGenericType(asSelectEntityType3, typeof(bool))) diff --git a/FreeSql/Internal/CommonProvider/CodeFirstProvider.cs b/FreeSql/Internal/CommonProvider/CodeFirstProvider.cs new file mode 100644 index 00000000..5a12ce5b --- /dev/null +++ b/FreeSql/Internal/CommonProvider/CodeFirstProvider.cs @@ -0,0 +1,75 @@ +using FreeSql.DataAnnotations; +using FreeSql.Extensions.EntityUtil; +using FreeSql.Internal.Model; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace FreeSql.Internal.CommonProvider { + + public abstract partial class CodeFirstProvider : ICodeFirst { + + protected IFreeSql _orm; + protected CommonUtils _commonUtils; + protected CommonExpression _commonExpression; + public CodeFirstProvider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) { + _orm = orm; + _commonUtils = commonUtils; + _commonExpression = commonExpression; + } + + public bool IsAutoSyncStructure { get; set; } = false; + public bool IsSyncStructureToLower { get; set; } = false; + public bool IsSyncStructureToUpper { get; set; } = false; + public bool IsConfigEntityFromDbFirst { get; set; } = false; + public bool IsNoneCommandParameter { get; set; } = false; + public bool IsLazyLoading { get; set; } = false; + + public abstract (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type); + + public ICodeFirst ConfigEntity(Action> entity) => _commonUtils.ConfigEntity(entity); + public ICodeFirst ConfigEntity(Type type, Action entity) => _commonUtils.ConfigEntity(type, entity); + public TableAttribute GetConfigEntity(Type type) => _commonUtils.GetConfigEntity(type); + public TableInfo GetTableByEntity(Type type) => _commonUtils.GetTableByEntity(type); + + public string GetComparisonDDLStatements() => this.GetComparisonDDLStatements(typeof(TEntity)); + public abstract string GetComparisonDDLStatements(params Type[] entityTypes); + + static object syncStructureLock = new object(); + internal ConcurrentDictionary dicSyced = new ConcurrentDictionary(); + public bool SyncStructure() => this.SyncStructure(typeof(TEntity)); + public bool SyncStructure(params Type[] entityTypes) { + if (entityTypes == null) return true; + var syncTypes = entityTypes.Where(a => dicSyced.ContainsKey(a.FullName) == false).ToArray(); + if (syncTypes.Any() == false) return true; + var before = new Aop.SyncStructureBeforeEventArgs(entityTypes); + _orm.Aop.SyncStructureBefore?.Invoke(this, before); + Exception exception = null; + string ddl = null; + try { + lock (syncStructureLock) { + ddl = this.GetComparisonDDLStatements(syncTypes); + if (string.IsNullOrEmpty(ddl)) { + foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); + return true; + } + var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl); + foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); + return affrows > 0; + } + } catch (Exception ex) { + exception = ex; + throw ex; + } finally { + var after = new Aop.SyncStructureAfterEventArgs(before, ddl, exception); + _orm.Aop.SyncStructureAfter?.Invoke(this, after); + } + } + } +} \ No newline at end of file diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs index 15009f2e..e66dce58 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs @@ -159,6 +159,7 @@ namespace FreeSql.Internal.CommonProvider { if (typeof(TReturn) == typeof(T1)) return this as ISelect; _tables[0].Parameter = select.Parameters[0]; _selectExpression = select.Body; + (_orm.CodeFirst as CodeFirstProvider).dicSyced.TryAdd(typeof(TReturn).FullName, true); var ret = _orm.Select(); Select0Provider, T1>.CopyData(this, ret, null); return ret; @@ -172,6 +173,7 @@ namespace FreeSql.Internal.CommonProvider { ), SelectTableInfoType.InnerJoin); if (typeof(TResult) == typeof(T1)) return this as ISelect; _selectExpression = resultSelector.Body; + (_orm.CodeFirst as CodeFirstProvider).dicSyced.TryAdd(typeof(TResult).FullName, true); var ret = _orm.Select() as Select1Provider; Select0Provider, T1>.CopyData(this, ret, null); return ret; @@ -185,6 +187,7 @@ namespace FreeSql.Internal.CommonProvider { ), SelectTableInfoType.InnerJoin); if (typeof(TResult) == typeof(T1)) return this as ISelect; _selectExpression = resultSelector.Body; + (_orm.CodeFirst as CodeFirstProvider).dicSyced.TryAdd(typeof(TResult).FullName, true); var ret = _orm.Select() as Select1Provider; Select0Provider, T1>.CopyData(this, ret, null); return ret; @@ -211,6 +214,7 @@ namespace FreeSql.Internal.CommonProvider { } if (typeof(TResult) == typeof(T1)) return this as ISelect; _selectExpression = resultSelector.Body; + (_orm.CodeFirst as CodeFirstProvider).dicSyced.TryAdd(typeof(TResult).FullName, true); var ret = _orm.Select() as Select1Provider; Select0Provider, T1>.CopyData(this, ret, null); return ret; diff --git a/FreeSql/Internal/UtilsExpressionTree.cs b/FreeSql/Internal/UtilsExpressionTree.cs index f439171c..ca0cd16b 100644 --- a/FreeSql/Internal/UtilsExpressionTree.cs +++ b/FreeSql/Internal/UtilsExpressionTree.cs @@ -231,6 +231,7 @@ namespace FreeSql.Internal { $"{pnv.PropertyType.Namespace}.{pnv.PropertyType.Name.Remove(pnv.PropertyType.Name.IndexOf('`'))}<{string.Join(", ", pnv.PropertyType.GenericTypeArguments.Select(a => a.IsNested ? $"{a.DeclaringType.Namespace}.{a.DeclaringType.Name}.{a.Name}" : $"{a.Namespace}.{a.Name}"))}>" : (pnv.PropertyType.IsNested ? $"{pnv.PropertyType.DeclaringType.Namespace}.{pnv.PropertyType.DeclaringType.Name}.{pnv.PropertyType.Name}" : $"{pnv.PropertyType.Namespace}.{pnv.PropertyType.Name}"); + var pnvBind = pnv.GetCustomAttribute()?.Bind.Split(',').Select(a => a.Trim()).Where(a => !string.IsNullOrEmpty(a)).ToArray(); var nvref = new TableRef(); nvref.Property = pnv; @@ -241,7 +242,7 @@ namespace FreeSql.Internal { if (trytb.Primarys.Any() == false) { nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 解析错误,实体类型 {trytbTypeName} 缺少主键标识,[Column(IsPrimary = true)]"); trytb.AddOrUpdateTableRef(pnv.Name, nvref); - if (isLazy) throw nvref.Exception; + //if (isLazy) throw nvref.Exception; continue; } @@ -259,7 +260,7 @@ namespace FreeSql.Internal { if (tbref.Primarys.Any() == false) { nvref.Exception = new Exception($"【ManyToMany】导航属性 {trytbTypeName}.{pnv.Name} 解析错误,实体类型 {tbrefTypeName} 缺少主键标识,[Column(IsPrimary = true)]"); trytb.AddOrUpdateTableRef(pnv.Name, nvref); - if (isLazy) throw nvref.Exception; + //if (isLazy) throw nvref.Exception; continue; } @@ -376,14 +377,14 @@ namespace FreeSql.Internal { if (trycol != null && trycol.CsType.NullableTypeOrThis() != trytb.Primarys[a].CsType) { nvref.Exception = new Exception($"【ManyToMany】导航属性 {trytbTypeName}.{pnv.Name} 解析错误,{tbmid.CsName}.{trycol.CsName} 和 {trytb.CsName}.{trytb.Primarys[a].CsName} 类型不一致"); trytb.AddOrUpdateTableRef(pnv.Name, nvref); - if (isLazy) throw nvref.Exception; - continue; + //if (isLazy) throw nvref.Exception; + break; } if (trycol == null) { nvref.Exception = new Exception($"【ManyToMany】导航属性 {trytbTypeName}.{pnv.Name} 在 {tbmid.CsName} 中没有找到对应的字段,如:{midTypePropsTrytb.Name}{findtrytbPkCsName}、{midTypePropsTrytb.Name}_{findtrytbPkCsName}"); trytb.AddOrUpdateTableRef(pnv.Name, nvref); - if (isLazy) throw nvref.Exception; - continue; + //if (isLazy) throw nvref.Exception; + break; } nvref.Columns.Add(trytb.Primarys[a]); @@ -397,34 +398,36 @@ namespace FreeSql.Internal { } } - var midTypePropsTbref = tbmid.Properties.Where(a => a.Value.PropertyType == tbref.Type).FirstOrDefault().Value; - for (var a = 0; a < tbref.Primarys.Length; a++) { - var findtbrefPkCsName = tbref.Primarys[a].CsName.TrimStart('_'); - if (findtbrefPkCsName.StartsWith(tbref.Type.Name, StringComparison.CurrentCultureIgnoreCase)) findtbrefPkCsName = findtbrefPkCsName.Substring(tbref.Type.Name.Length).TrimStart('_'); - if (tbmid.ColumnsByCs.TryGetValue($"{midTypePropsTbref.Name}{findtbrefPkCsName}", out var trycol) == false && //骆峰命名 - tbmid.ColumnsByCs.TryGetValue($"{midTypePropsTbref.Name}_{findtbrefPkCsName}", out trycol) == false //下划线命名 - ) { + if (nvref.Exception == null) { + var midTypePropsTbref = tbmid.Properties.Where(a => a.Value.PropertyType == tbref.Type).FirstOrDefault().Value; + for (var a = 0; a < tbref.Primarys.Length; a++) { + var findtbrefPkCsName = tbref.Primarys[a].CsName.TrimStart('_'); + if (findtbrefPkCsName.StartsWith(tbref.Type.Name, StringComparison.CurrentCultureIgnoreCase)) findtbrefPkCsName = findtbrefPkCsName.Substring(tbref.Type.Name.Length).TrimStart('_'); + if (tbmid.ColumnsByCs.TryGetValue($"{midTypePropsTbref.Name}{findtbrefPkCsName}", out var trycol) == false && //骆峰命名 + tbmid.ColumnsByCs.TryGetValue($"{midTypePropsTbref.Name}_{findtbrefPkCsName}", out trycol) == false //下划线命名 + ) { - } - if (trycol != null && trycol.CsType.NullableTypeOrThis() != tbref.Primarys[a].CsType) { - nvref.Exception = new Exception($"【ManyToMany】导航属性 {tbrefTypeName}.{pnv.Name} 解析错误,{tbmid.CsName}.{trycol.CsName} 和 {tbref.CsName}.{tbref.Primarys[a].CsName} 类型不一致"); - trytb.AddOrUpdateTableRef(pnv.Name, nvref); - if (isLazy) throw nvref.Exception; - continue; - } - if (trycol == null) { - nvref.Exception = new Exception($"【ManyToMany】导航属性 {tbrefTypeName}.{pnv.Name} 在 {tbmid.CsName} 中没有找到对应的字段,如:{midTypePropsTbref.Name}{findtbrefPkCsName}、{midTypePropsTbref.Name}_{findtbrefPkCsName}"); - trytb.AddOrUpdateTableRef(pnv.Name, nvref); - if (isLazy) throw nvref.Exception; - continue; - } + } + if (trycol != null && trycol.CsType.NullableTypeOrThis() != tbref.Primarys[a].CsType) { + nvref.Exception = new Exception($"【ManyToMany】导航属性 {trytbTypeName}.{pnv.Name} 解析错误,{tbmid.CsName}.{trycol.CsName} 和 {tbref.CsName}.{tbref.Primarys[a].CsName} 类型不一致"); + trytb.AddOrUpdateTableRef(pnv.Name, nvref); + //if (isLazy) throw nvref.Exception; + break; + } + if (trycol == null) { + nvref.Exception = new Exception($"【ManyToMany】导航属性 {trytbTypeName}.{pnv.Name} 在 {tbmid.CsName} 中没有找到对应的字段,如:{midTypePropsTbref.Name}{findtbrefPkCsName}、{midTypePropsTbref.Name}_{findtbrefPkCsName}"); + trytb.AddOrUpdateTableRef(pnv.Name, nvref); + //if (isLazy) throw nvref.Exception; + break; + } - nvref.RefColumns.Add(tbref.Primarys[a]); - nvref.MiddleColumns.Add(trycol); - if (tbmid.Primarys.Any() == false) - trycol.Attribute.IsPrimary = true; + nvref.RefColumns.Add(tbref.Primarys[a]); + nvref.MiddleColumns.Add(trycol); + if (tbmid.Primarys.Any() == false) + trycol.Attribute.IsPrimary = true; - if (isLazy) lmbdWhere.Append(" && b.").Append(trycol.CsName).Append(" == a.").Append(tbref.Primarys[a].CsName); + if (isLazy) lmbdWhere.Append(" && b.").Append(trycol.CsName).Append(" == a.").Append(tbref.Primarys[a].CsName); + } } if (nvref.Columns.Count > 0 && nvref.RefColumns.Count > 0) { nvref.RefMiddleEntityType = tbmid.Type; @@ -441,12 +444,17 @@ namespace FreeSql.Internal { .Append(" public override ").Append(propTypeName).Append(" ").Append(pnv.Name).AppendLine(" {"); if (vp.Item2) { //get 重写 cscode.Append(" get {\r\n") - .Append(" if (base.").Append(pnv.Name).Append(" == null && __lazy__").Append(pnv.Name).AppendLine(" == false) {") - .Append(" base.").Append(pnv.Name).Append(" = __fsql_orm__.Select<").Append(propElementType.IsNested ? $"{propElementType.DeclaringType.Namespace}.{propElementType.DeclaringType.Name}.{propElementType.Name}" : $"{propElementType.Namespace}.{propElementType.Name}") - .Append(">().Where(a => __fsql_orm__.Select<").Append(tbmid.Type.IsNested ? $"{tbmid.Type.DeclaringType.Namespace}.{tbmid.Type.DeclaringType.Name}.{tbmid.Type.Name}" : $"{tbmid.Type.Namespace}.{tbmid.Type.Name}") - .Append(">().Where(b => ").Append(lmbdWhere.ToString()).AppendLine(").Any()).ToList();"); - cscode.Append(" __lazy__").Append(pnv.Name).AppendLine(" = true;") - .Append(" }\r\n") + .Append(" if (base.").Append(pnv.Name).Append(" == null && __lazy__").Append(pnv.Name).AppendLine(" == false) {"); + + if (nvref.Exception == null) + cscode.Append(" base.").Append(pnv.Name).Append(" = __fsql_orm__.Select<").Append(propElementType.IsNested ? $"{propElementType.DeclaringType.Namespace}.{propElementType.DeclaringType.Name}.{propElementType.Name}" : $"{propElementType.Namespace}.{propElementType.Name}") + .Append(">().Where(a => __fsql_orm__.Select<").Append(tbmid.Type.IsNested ? $"{tbmid.Type.DeclaringType.Namespace}.{tbmid.Type.DeclaringType.Name}.{tbmid.Type.Name}" : $"{tbmid.Type.Namespace}.{tbmid.Type.Name}") + .Append(">().Where(b => ").Append(lmbdWhere.ToString()).AppendLine(").Any()).ToList();") + .Append(" __lazy__").Append(pnv.Name).AppendLine(" = true;"); + else + cscode.Append(" throw new Exception(\"").Append(nvref.Exception.Message.Replace("\r\n", "\\r\\n").Replace("\"", "\\\"")).AppendLine("\");"); + + cscode.Append(" }\r\n") .Append(" return base.").Append(pnv.Name).AppendLine(";") .Append(" }\r\n"); } @@ -456,16 +464,39 @@ namespace FreeSql.Internal { cscode.AppendLine(" }"); } } else { //One To Many + List bindColumns = new List(); + if (pnvBind != null) { + foreach(var bi in pnvBind) { + if (tbref.ColumnsByCs.TryGetValue(bi, out var trybindcol) == false) { + nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 特性 [Navigate] 解析错误,在 {tbrefTypeName} 未找到属性:{bi}"); + trytb.AddOrUpdateTableRef(pnv.Name, nvref); + //if (isLazy) throw nvref.Exception; + break; + } + bindColumns.Add(trybindcol); + } + } + + PropertyInfo refprop = null; var refcols = tbref.Properties.Where(z => z.Value.PropertyType == trytb.Type); - var refprop = refcols.Count() == 1 ? refcols.First().Value : null; + refprop = refcols.Count() == 1 ? refcols.First().Value : null; var lmbdWhere = isLazy ? new StringBuilder() : null; - for (var a = 0; a < trytb.Primarys.Length; a++) { + + if (nvref.Exception == null && bindColumns.Any() && bindColumns.Count != trytb.Primarys.Length) { + nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 特性 [Navigate] Bind 数目({bindColumns.Count}) 与 内部主键数目({trytb.Primarys.Length}) 不相同"); + trytb.AddOrUpdateTableRef(pnv.Name, nvref); + //if (isLazy) throw nvref.Exception; + } + for (var a = 0; nvref.Exception == null && a < trytb.Primarys.Length; a++) { var findtrytbPkCsName = trytb.Primarys[a].CsName.TrimStart('_'); if (findtrytbPkCsName.StartsWith(trytb.Type.Name, StringComparison.CurrentCultureIgnoreCase)) findtrytbPkCsName = findtrytbPkCsName.Substring(trytb.Type.Name.Length).TrimStart('_'); var findtrytb = pnv.Name; if (findtrytb.EndsWith(tbref.CsName + "s")) findtrytb = findtrytb.Substring(0, findtrytb.Length - tbref.CsName.Length - 1); findtrytb += trytb.CsName; - if (tbref.ColumnsByCs.TryGetValue($"{findtrytb}{findtrytbPkCsName}", out var trycol) == false && //骆峰命名 + + var trycol = bindColumns.Any() ? bindColumns[a] : null; + if (trycol == null && + tbref.ColumnsByCs.TryGetValue($"{findtrytb}{findtrytbPkCsName}", out trycol) == false && //骆峰命名 tbref.ColumnsByCs.TryGetValue($"{findtrytb}_{findtrytbPkCsName}", out trycol) == false //下划线命名 ) { if (refprop != null && @@ -474,18 +505,18 @@ namespace FreeSql.Internal { { } - if (trycol != null && trycol.CsType.NullableTypeOrThis() != trytb.Primarys[a].CsType) { - nvref.Exception = new Exception($"【OneToMany】导航属性 {trytbTypeName}.{pnv.Name} 解析错误,{trytb.CsName}.{trytb.Primarys[a].CsName} 和 {tbref.CsName}.{trycol.CsName} 类型不一致"); - trytb.AddOrUpdateTableRef(pnv.Name, nvref); - //if (isLazy) throw nvref.Exception; - continue; - } - if (trycol == null) { - nvref.Exception = new Exception($"【OneToMany】导航属性 {trytbTypeName}.{pnv.Name} 在 {tbref.CsName} 中没有找到对应的字段,如:{findtrytb}{findtrytbPkCsName}、{findtrytb}_{findtrytbPkCsName}" + (refprop == null ? "" : $"、{refprop.Name}{findtrytbPkCsName}、{refprop.Name}_{findtrytbPkCsName}")); - trytb.AddOrUpdateTableRef(pnv.Name, nvref); - //if (isLazy) throw nvref.Exception; - continue; - } + } + if (trycol != null && trycol.CsType.NullableTypeOrThis() != trytb.Primarys[a].CsType) { + nvref.Exception = new Exception($"【OneToMany】导航属性 {trytbTypeName}.{pnv.Name} 解析错误,{trytb.CsName}.{trytb.Primarys[a].CsName} 和 {tbref.CsName}.{trycol.CsName} 类型不一致"); + trytb.AddOrUpdateTableRef(pnv.Name, nvref); + //if (isLazy) throw nvref.Exception; + break; + } + if (trycol == null) { + nvref.Exception = new Exception($"【OneToMany】导航属性 {trytbTypeName}.{pnv.Name} 在 {tbref.CsName} 中没有找到对应的字段,如:{findtrytb}{findtrytbPkCsName}、{findtrytb}_{findtrytbPkCsName}" + (refprop == null ? "" : $"、{refprop.Name}{findtrytbPkCsName}、{refprop.Name}_{findtrytbPkCsName}")); + trytb.AddOrUpdateTableRef(pnv.Name, nvref); + //if (isLazy) throw nvref.Exception; + break; } nvref.Columns.Add(trytb.Primarys[a]); @@ -545,20 +576,42 @@ namespace FreeSql.Internal { if (tbref.Primarys.Any() == false) { nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 解析错误,实体类型 {propTypeName} 缺少主键标识,[Column(IsPrimary = true)]"); trytb.AddOrUpdateTableRef(pnv.Name, nvref); - if (isLazy) throw nvref.Exception; - continue; + //if (isLazy) throw nvref.Exception; } + var tbrefTypeName = tbref.Type.IsNested ? $"{tbref.Type.DeclaringType.Namespace}.{tbref.Type.DeclaringType.Name}.{tbref.Type.Name}" : $"{tbref.Type.Namespace}.{tbref.Type.Name}"; var isOnoToOne = pnv.PropertyType != trytb.Type && tbref.Properties.Where(z => z.Value.PropertyType == trytb.Type).Any() && tbref.Primarys.Length == trytb.Primarys.Length && string.Join(",", tbref.Primarys.Select(a => a.CsType.FullName).OrderBy(a => a)) == string.Join(",", trytb.Primarys.Select(a => a.CsType.FullName).OrderBy(a => a)); + + List bindColumns = new List(); + if (pnvBind != null) { + foreach(var bi in pnvBind) { + if (trytb.ColumnsByCs.TryGetValue(bi, out var trybindcol) == false) { + nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 特性 [Navigate] 解析错误,在 {trytbTypeName} 未找到属性:{bi}"); + trytb.AddOrUpdateTableRef(pnv.Name, nvref); + //if (isLazy) throw nvref.Exception; + break; + } + bindColumns.Add(trybindcol); + } + } var lmbdWhere = new StringBuilder(); - for (var a = 0; a < tbref.Primarys.Length; a++) { + + if (nvref.Exception == null && bindColumns.Any() && bindColumns.Count != tbref.Primarys.Length) { + nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 特性 [Navigate] Bind 数目({bindColumns.Count}) 与 外部主键数目({tbref.Primarys.Length}) 不相同"); + trytb.AddOrUpdateTableRef(pnv.Name, nvref); + //if (isLazy) throw nvref.Exception; + } + for (var a = 0; nvref.Exception == null && a < tbref.Primarys.Length; a++) { var findtbrefPkCsName = tbref.Primarys[a].CsName.TrimStart('_'); if (findtbrefPkCsName.StartsWith(tbref.Type.Name, StringComparison.CurrentCultureIgnoreCase)) findtbrefPkCsName = findtbrefPkCsName.Substring(tbref.Type.Name.Length).TrimStart('_'); - if (trytb.ColumnsByCs.TryGetValue($"{pnv.Name}{findtbrefPkCsName}", out var trycol) == false && //骆峰命名 + + var trycol = bindColumns.Any() ? bindColumns[a] : null; + if (trycol == null && + trytb.ColumnsByCs.TryGetValue($"{pnv.Name}{findtbrefPkCsName}", out trycol) == false && //骆峰命名 trytb.ColumnsByCs.TryGetValue($"{pnv.Name}_{findtbrefPkCsName}", out trycol) == false && //下划线命名 - //tbref.Primarys.Length == 1 && + //tbref.Primarys.Length == 1 && trytb.ColumnsByCs.TryGetValue($"{pnv.Name}_Id", out trycol) == false && trytb.ColumnsByCs.TryGetValue($"{pnv.Name}Id", out trycol) == false ) { @@ -579,19 +632,18 @@ namespace FreeSql.Internal { } } } - if (trycol != null && trycol.CsType.NullableTypeOrThis() != tbref.Primarys[a].CsType) { - nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 解析错误,{trytb.CsName}.{trycol.CsName} 和 {tbref.CsName}.{tbref.Primarys[a].CsName} 类型不一致"); - trytb.AddOrUpdateTableRef(pnv.Name, nvref); - if (isLazy) throw nvref.Exception; - continue; - } } - + if (trycol != null && trycol.CsType.NullableTypeOrThis() != tbref.Primarys[a].CsType) { + nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 解析错误,{trytb.CsName}.{trycol.CsName} 和 {tbref.CsName}.{tbref.Primarys[a].CsName} 类型不一致"); + trytb.AddOrUpdateTableRef(pnv.Name, nvref); + //if (isLazy) throw nvref.Exception; + break; + } if (trycol == null) { nvref.Exception = new Exception($"导航属性 {trytbTypeName}.{pnv.Name} 没有找到对应的字段,如:{pnv.Name}{findtbrefPkCsName}、{pnv.Name}_{findtbrefPkCsName}"); trytb.AddOrUpdateTableRef(pnv.Name, nvref); //if (isLazy) throw nvref.Exception; - continue; + break; } nvref.Columns.Add(trycol); @@ -658,7 +710,7 @@ namespace FreeSql.Internal { } static Lazy MethodLazyLoadingComplier = new Lazy(() => { var type = Type.GetType("FreeSql.Extensions.LazyLoading.LazyLoadingComplier,FreeSql.Extensions.LazyLoading"); - return type.GetMethod("CompileCode"); + return type?.GetMethod("CompileCode"); }); public static T[] GetDbParamtersByObject(string sql, object obj, string paramPrefix, Func constructorParamter) { diff --git a/Providers/FreeSql.Provider.MySql/FreeSql.Provider.MySql.csproj b/Providers/FreeSql.Provider.MySql/FreeSql.Provider.MySql.csproj index 6a343c57..e474560d 100644 --- a/Providers/FreeSql.Provider.MySql/FreeSql.Provider.MySql.csproj +++ b/Providers/FreeSql.Provider.MySql/FreeSql.Provider.MySql.csproj @@ -2,7 +2,7 @@ netstandard2.0;net452 - 0.6.3 + 0.6.4 true YeXiangQin FreeSql 数据库实现,基于 MySql 5.6 diff --git a/Providers/FreeSql.Provider.MySql/MySqlCodeFirst.cs b/Providers/FreeSql.Provider.MySql/MySqlCodeFirst.cs index 86d0e7db..6148c2a0 100644 --- a/Providers/FreeSql.Provider.MySql/MySqlCodeFirst.cs +++ b/Providers/FreeSql.Provider.MySql/MySqlCodeFirst.cs @@ -13,22 +13,9 @@ using System.Text.RegularExpressions; namespace FreeSql.MySql { - class MySqlCodeFirst : ICodeFirst { - IFreeSql _orm; - protected CommonUtils _commonUtils; - protected CommonExpression _commonExpression; - public MySqlCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) { - _orm = orm; - _commonUtils = commonUtils; - _commonExpression = commonExpression; - } + class MySqlCodeFirst : Internal.CommonProvider.CodeFirstProvider { - public bool IsAutoSyncStructure { get; set; } = false; - public bool IsSyncStructureToLower { get; set; } = false; - public bool IsSyncStructureToUpper { get; set; } = false; - public bool IsConfigEntityFromDbFirst { get; set; } = false; - public bool IsNoneCommandParameter { get; set; } = false; - public bool IsLazyLoading { get; set; } = false; + public MySqlCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) : base(orm, commonUtils, commonExpression) { } static object _dicCsToDbLock = new object(); static Dictionary _dicCsToDb = new Dictionary() { @@ -64,7 +51,7 @@ namespace FreeSql.MySql { { typeof(MygisMultiPolygon).FullName, (MySqlDbType.Geometry, "multipolygon", "multipolygon", false, null, new MygisMultiPolygon(new[]{new MygisPolygon(new[]{new[]{new MygisCoordinate2D(),new MygisCoordinate2D()},new[]{new MygisCoordinate2D(),new MygisCoordinate2D()}}),new MygisPolygon(new[]{new[]{new MygisCoordinate2D(),new MygisCoordinate2D()},new[]{new MygisCoordinate2D(),new MygisCoordinate2D()}})})) }, }; - public (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { + public override (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { if (_dicCsToDb.TryGetValue(type.FullName, out var trydc)) return new (int, string, string, bool?, object)?(((int)trydc.type, trydc.dbtype, trydc.dbtypeFull, trydc.isnullable, trydc.defaultValue)); if (type.IsArray) return null; var enumType = type.IsEnum ? type : null; @@ -85,8 +72,7 @@ namespace FreeSql.MySql { return null; } - public string GetComparisonDDLStatements() => this.GetComparisonDDLStatements(typeof(TEntity)); - public string GetComparisonDDLStatements(params Type[] entityTypes) { + public override string GetComparisonDDLStatements(params Type[] entityTypes) { var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5)); var database = conn.Value.Database; Func ExecuteScalar = (db, sql) => { @@ -205,6 +191,7 @@ where a.table_schema in ({0}) and a.table_name in ({1})", tboldname ?? tbname); } //添加列 sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType); + if (tbcol.Attribute.IsNullable == false) sbalter.Append(" DEFAULT ").Append(_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue)); if (isIdentityChanged) sbalter.Append(" AUTO_INCREMENT").Append(existsPrimary == null ? "" : ", DROP PRIMARY KEY").Append(", ADD PRIMARY KEY(").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(")"); sbalter.Append(";\r\n"); } @@ -286,40 +273,5 @@ where a.constraint_schema IN ({0}) and a.table_name IN ({1})", tboldname ?? tbna } } } - - static object syncStructureLock = new object(); - ConcurrentDictionary dicSyced = new ConcurrentDictionary(); - public bool SyncStructure() => this.SyncStructure(typeof(TEntity)); - public bool SyncStructure(params Type[] entityTypes) { - if (entityTypes == null) return true; - var syncTypes = entityTypes.Where(a => dicSyced.ContainsKey(a.FullName) == false).ToArray(); - if (syncTypes.Any() == false) return true; - var before = new Aop.SyncStructureBeforeEventArgs(entityTypes); - _orm.Aop.SyncStructureBefore?.Invoke(this, before); - Exception exception = null; - string ddl = null; - try { - lock (syncStructureLock) { - ddl = this.GetComparisonDDLStatements(syncTypes); - if (string.IsNullOrEmpty(ddl)) { - foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); - return true; - } - var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl); - foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); - return affrows > 0; - } - } catch (Exception ex) { - exception = ex; - throw ex; - } finally { - var after = new Aop.SyncStructureAfterEventArgs(before, ddl, exception); - _orm.Aop.SyncStructureAfter?.Invoke(this, after); - } - } - public ICodeFirst ConfigEntity(Action> entity) => _commonUtils.ConfigEntity(entity); - public ICodeFirst ConfigEntity(Type type, Action entity) => _commonUtils.ConfigEntity(type, entity); - public TableAttribute GetConfigEntity(Type type) => _commonUtils.GetConfigEntity(type); - public TableInfo GetTableByEntity(Type type) => _commonUtils.GetTableByEntity(type); } } \ No newline at end of file diff --git a/Providers/FreeSql.Provider.MySqlConnector/FreeSql.Provider.MySqlConnector.csproj b/Providers/FreeSql.Provider.MySqlConnector/FreeSql.Provider.MySqlConnector.csproj index 7cf27c37..280f0170 100644 --- a/Providers/FreeSql.Provider.MySqlConnector/FreeSql.Provider.MySqlConnector.csproj +++ b/Providers/FreeSql.Provider.MySqlConnector/FreeSql.Provider.MySqlConnector.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45 - 0.6.3 + 0.6.4 true YeXiangQin FreeSql 数据库实现,基于 MySql 5.6 diff --git a/Providers/FreeSql.Provider.Oracle/FreeSql.Provider.Oracle.csproj b/Providers/FreeSql.Provider.Oracle/FreeSql.Provider.Oracle.csproj index 65a25680..81b5a530 100644 --- a/Providers/FreeSql.Provider.Oracle/FreeSql.Provider.Oracle.csproj +++ b/Providers/FreeSql.Provider.Oracle/FreeSql.Provider.Oracle.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45 - 0.6.3 + 0.6.4 true YeXiangQin FreeSql 数据库实现,基于 Oracle 11 diff --git a/Providers/FreeSql.Provider.Oracle/OracleCodeFirst.cs b/Providers/FreeSql.Provider.Oracle/OracleCodeFirst.cs index 9209933e..6893b677 100644 --- a/Providers/FreeSql.Provider.Oracle/OracleCodeFirst.cs +++ b/Providers/FreeSql.Provider.Oracle/OracleCodeFirst.cs @@ -13,22 +13,9 @@ using System.Text.RegularExpressions; namespace FreeSql.Oracle { - class OracleCodeFirst : ICodeFirst { - IFreeSql _orm; - protected CommonUtils _commonUtils; - protected CommonExpression _commonExpression; - public OracleCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) { - _orm = orm; - _commonUtils = commonUtils; - _commonExpression = commonExpression; - } + class OracleCodeFirst : Internal.CommonProvider.CodeFirstProvider { - public bool IsAutoSyncStructure { get; set; } = false; - public bool IsSyncStructureToLower { get; set; } = false; - public bool IsSyncStructureToUpper { get; set; } = false; - public bool IsConfigEntityFromDbFirst { get; set; } = false; - public bool IsNoneCommandParameter { get; set; } = false; - public bool IsLazyLoading { get; set; } = false; + public OracleCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) : base(orm, commonUtils, commonExpression) { } static object _dicCsToDbLock = new object(); static Dictionary _dicCsToDb = new Dictionary() { @@ -58,7 +45,7 @@ namespace FreeSql.Oracle { { typeof(Guid).FullName, (OracleDbType.Char, "char", "char(36 CHAR) NOT NULL", false, false, Guid.Empty) },{ typeof(Guid?).FullName, (OracleDbType.Char, "char", "char(36 CHAR) NULL", false, true, null) }, }; - public (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { + public override (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { if (_dicCsToDb.TryGetValue(type.FullName, out var trydc)) return new (int, string, string, bool?, object)?(((int)trydc.type, trydc.dbtype, trydc.dbtypeFull, trydc.isnullable, trydc.defaultValue)); if (type.IsArray) return null; var enumType = type.IsEnum ? type : null; @@ -78,8 +65,7 @@ namespace FreeSql.Oracle { return null; } - public string GetComparisonDDLStatements() => this.GetComparisonDDLStatements(typeof(TEntity)); - public string GetComparisonDDLStatements(params Type[] entityTypes) { + public override string GetComparisonDDLStatements(params Type[] entityTypes) { var userId = (_orm.Ado.MasterPool as OracleConnectionPool).UserId; var seqcols = new List<(ColumnInfo, string[], bool)>(); //序列 @@ -333,40 +319,5 @@ and a.owner in ({0}) and a.table_name in ({1})", tboldname ?? tbname); sqlType += $"({data_length})"; return sqlType; } - - static object syncStructureLock = new object(); - ConcurrentDictionary dicSyced = new ConcurrentDictionary(); - public bool SyncStructure() => this.SyncStructure(typeof(TEntity)); - public bool SyncStructure(params Type[] entityTypes) { - if (entityTypes == null) return true; - var syncTypes = entityTypes.Where(a => dicSyced.ContainsKey(a.FullName) == false).ToArray(); - if (syncTypes.Any() == false) return true; - var before = new Aop.SyncStructureBeforeEventArgs(entityTypes); - _orm.Aop.SyncStructureBefore?.Invoke(this, before); - Exception exception = null; - string ddl = null; - try { - lock (syncStructureLock) { - ddl = this.GetComparisonDDLStatements(syncTypes); - if (string.IsNullOrEmpty(ddl)) { - foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); - return true; - } - var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl); - foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); - return affrows > 0; - } - } catch (Exception ex) { - exception = ex; - throw ex; - } finally { - var after = new Aop.SyncStructureAfterEventArgs(before, ddl, exception); - _orm.Aop.SyncStructureAfter?.Invoke(this, after); - } - } - public ICodeFirst ConfigEntity(Action> entity) => _commonUtils.ConfigEntity(entity); - public ICodeFirst ConfigEntity(Type type, Action entity) => _commonUtils.ConfigEntity(type, entity); - public TableAttribute GetConfigEntity(Type type) => _commonUtils.GetConfigEntity(type); - public TableInfo GetTableByEntity(Type type) => _commonUtils.GetTableByEntity(type); } } \ No newline at end of file diff --git a/Providers/FreeSql.Provider.Oracle/OracleDbFirst.cs b/Providers/FreeSql.Provider.Oracle/OracleDbFirst.cs index 8a9ef894..087580ad 100644 --- a/Providers/FreeSql.Provider.Oracle/OracleDbFirst.cs +++ b/Providers/FreeSql.Provider.Oracle/OracleDbFirst.cs @@ -58,6 +58,9 @@ namespace FreeSql.Oracle { case "interval day to second": _dicDbToCs.TryAdd(dbfull, _dicDbToCs["interval day(2) to second(6)"]); return OracleDbType.IntervalDS; + case "date": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["date(7)"]); + return OracleDbType.IntervalDS; case "timestamp": _dicDbToCs.TryAdd(dbfull, _dicDbToCs["timestamp(6)"]); return OracleDbType.TimeStamp; @@ -106,6 +109,7 @@ namespace FreeSql.Oracle { { "number(10,2)", ("(decimal?)", "decimal.Parse({0})", "{0}.ToString()", "decimal?", typeof(decimal), typeof(decimal?), "{0}.Value", "GetDecimal") }, { "interval day(2) to second(6)", ("(TimeSpan?)", "TimeSpan.Parse(double.Parse({0}))", "{0}.Ticks.ToString()", "TimeSpan?", typeof(TimeSpan), typeof(TimeSpan?), "{0}.Value", "GetValue") }, + { "date(7)", ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetValue") }, { "timestamp(6)", ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetValue") }, { "timestamp(6) with local time zone", ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetValue") }, diff --git a/Providers/FreeSql.Provider.PostgreSQL/FreeSql.Provider.PostgreSQL.csproj b/Providers/FreeSql.Provider.PostgreSQL/FreeSql.Provider.PostgreSQL.csproj index f72aa2fd..35993249 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/FreeSql.Provider.PostgreSQL.csproj +++ b/Providers/FreeSql.Provider.PostgreSQL/FreeSql.Provider.PostgreSQL.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45 - 0.6.3 + 0.6.4 true YeXiangQin FreeSql 数据库实现,基于 PostgreSQL 9.5 diff --git a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLCodeFirst.cs b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLCodeFirst.cs index 0c7da3c5..4568a53f 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLCodeFirst.cs +++ b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLCodeFirst.cs @@ -18,22 +18,9 @@ using System.Text.RegularExpressions; namespace FreeSql.PostgreSQL { - class PostgreSQLCodeFirst : ICodeFirst { - IFreeSql _orm; - protected CommonUtils _commonUtils; - protected CommonExpression _commonExpression; - public PostgreSQLCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) { - _orm = orm; - _commonUtils = commonUtils; - _commonExpression = commonExpression; - } + class PostgreSQLCodeFirst : Internal.CommonProvider.CodeFirstProvider { - public bool IsAutoSyncStructure { get; set; } = false; - public bool IsSyncStructureToLower { get; set; } = false; - public bool IsSyncStructureToUpper { get; set; } = false; - public bool IsConfigEntityFromDbFirst { get; set; } = false; - public bool IsNoneCommandParameter { get; set; } = false; - public bool IsLazyLoading { get; set; } = false; + public PostgreSQLCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) : base(orm, commonUtils, commonExpression) { } static object _dicCsToDbLock = new object(); static Dictionary _dicCsToDb = new Dictionary() { @@ -94,7 +81,7 @@ namespace FreeSql.PostgreSQL { { typeof(PostgisGeometryCollection).FullName, (NpgsqlDbType.Geometry, "geometry", "geometry", false, null, new PostgisGeometryCollection(new[]{new PostgisPoint(0, 0),new PostgisPoint(0, 0) })) }, }; - public (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { + public override (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { var isarray = type.FullName != "System.Byte[]" && type.IsArray; var elementType = isarray ? type.GetElementType() : type; var info = GetDbInfoNoneArray(elementType); @@ -122,9 +109,8 @@ namespace FreeSql.PostgreSQL { } return null; } - - public string GetComparisonDDLStatements() => this.GetComparisonDDLStatements(typeof(TEntity)); - public string GetComparisonDDLStatements(params Type[] entityTypes) { + + public override string GetComparisonDDLStatements(params Type[] entityTypes) { var sb = new StringBuilder(); var seqcols = new List<(ColumnInfo, string[], bool)>(); //序列 @@ -338,40 +324,5 @@ where pg_namespace.nspname={0} and pg_class.relname={1} and pg_constraint.contyp } return sb.Length == 0 ? null : sb.ToString(); } - - static object syncStructureLock = new object(); - ConcurrentDictionary dicSyced = new ConcurrentDictionary(); - public bool SyncStructure() => this.SyncStructure(typeof(TEntity)); - public bool SyncStructure(params Type[] entityTypes) { - if (entityTypes == null) return true; - var syncTypes = entityTypes.Where(a => dicSyced.ContainsKey(a.FullName) == false).ToArray(); - if (syncTypes.Any() == false) return true; - var before = new Aop.SyncStructureBeforeEventArgs(entityTypes); - _orm.Aop.SyncStructureBefore?.Invoke(this, before); - Exception exception = null; - string ddl = null; - try { - lock (syncStructureLock) { - ddl = this.GetComparisonDDLStatements(syncTypes); - if (string.IsNullOrEmpty(ddl)) { - foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); - return true; - } - var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl); - foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); - return affrows > 0; - } - } catch (Exception ex) { - exception = ex; - throw ex; - } finally { - var after = new Aop.SyncStructureAfterEventArgs(before, ddl, exception); - _orm.Aop.SyncStructureAfter?.Invoke(this, after); - } - } - public ICodeFirst ConfigEntity(Action> entity) => _commonUtils.ConfigEntity(entity); - public ICodeFirst ConfigEntity(Type type, Action entity) => _commonUtils.ConfigEntity(type, entity); - public TableAttribute GetConfigEntity(Type type) => _commonUtils.GetConfigEntity(type); - public TableInfo GetTableByEntity(Type type) => _commonUtils.GetTableByEntity(type); } } \ No newline at end of file diff --git a/Providers/FreeSql.Provider.SqlServer/FreeSql.Provider.SqlServer.csproj b/Providers/FreeSql.Provider.SqlServer/FreeSql.Provider.SqlServer.csproj index 06f8c7ab..c75f6439 100644 --- a/Providers/FreeSql.Provider.SqlServer/FreeSql.Provider.SqlServer.csproj +++ b/Providers/FreeSql.Provider.SqlServer/FreeSql.Provider.SqlServer.csproj @@ -2,7 +2,7 @@ netstandard2.0;net451 - 0.6.3 + 0.6.4 true YeXiangQin FreeSql 数据库实现,基于 SqlServer 2005+,并根据版本适配分页方法:row_number 或 offset fetch next diff --git a/Providers/FreeSql.Provider.SqlServer/SqlServerCodeFirst.cs b/Providers/FreeSql.Provider.SqlServer/SqlServerCodeFirst.cs index 4fb6cf4b..1356b66f 100644 --- a/Providers/FreeSql.Provider.SqlServer/SqlServerCodeFirst.cs +++ b/Providers/FreeSql.Provider.SqlServer/SqlServerCodeFirst.cs @@ -12,22 +12,9 @@ using System.Text.RegularExpressions; namespace FreeSql.SqlServer { - class SqlServerCodeFirst : ICodeFirst { - IFreeSql _orm; - protected CommonUtils _commonUtils; - protected CommonExpression _commonExpression; - public SqlServerCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) { - _orm = orm; - _commonUtils = commonUtils; - _commonExpression = commonExpression; - } - - public bool IsAutoSyncStructure { get; set; } = false; - public bool IsSyncStructureToLower { get; set; } = false; - public bool IsSyncStructureToUpper { get; set; } = false; - public bool IsConfigEntityFromDbFirst { get; set; } = false; - public bool IsNoneCommandParameter { get; set; } = false; - public bool IsLazyLoading { get; set; } = false; + class SqlServerCodeFirst : Internal.CommonProvider.CodeFirstProvider { + + public SqlServerCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) : base(orm, commonUtils, commonExpression) { } static object _dicCsToDbLock = new object(); static Dictionary _dicCsToDb = new Dictionary() { @@ -57,7 +44,7 @@ namespace FreeSql.SqlServer { { typeof(Guid).FullName, (SqlDbType.UniqueIdentifier, "uniqueidentifier", "uniqueidentifier NOT NULL", false, false, Guid.Empty) },{ typeof(Guid?).FullName, (SqlDbType.UniqueIdentifier, "uniqueidentifier", "uniqueidentifier", false, true, null) }, }; - public (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { + public override (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { if (_dicCsToDb.TryGetValue(type.FullName, out var trydc)) return new (int, string, string, bool?, object)?(((int)trydc.type, trydc.dbtype, trydc.dbtypeFull, trydc.isnullable, trydc.defaultValue)); if (type.IsArray) return null; var enumType = type.IsEnum ? type : null; @@ -76,9 +63,8 @@ namespace FreeSql.SqlServer { } return null; } - - public string GetComparisonDDLStatements() => this.GetComparisonDDLStatements(typeof(TEntity)); - public string GetComparisonDDLStatements(params Type[] entityTypes) { + + public override string GetComparisonDDLStatements(params Type[] entityTypes) { var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5)); var database = conn.Value.Database; Func ExecuteScalar = (db, sql) => { @@ -326,41 +312,5 @@ use " + database, tboldname ?? tbname); } return ddv; } - - - static object syncStructureLock = new object(); - ConcurrentDictionary dicSyced = new ConcurrentDictionary(); - public bool SyncStructure() => this.SyncStructure(typeof(TEntity)); - public bool SyncStructure(params Type[] entityTypes) { - if (entityTypes == null) return true; - var syncTypes = entityTypes.Where(a => dicSyced.ContainsKey(a.FullName) == false).ToArray(); - if (syncTypes.Any() == false) return true; - var before = new Aop.SyncStructureBeforeEventArgs(entityTypes); - _orm.Aop.SyncStructureBefore?.Invoke(this, before); - Exception exception = null; - string ddl = null; - try { - lock (syncStructureLock) { - ddl = this.GetComparisonDDLStatements(syncTypes); - if (string.IsNullOrEmpty(ddl)) { - foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); - return true; - } - var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl); - foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); - return affrows > 0; - } - } catch (Exception ex) { - exception = ex; - throw ex; - } finally { - var after = new Aop.SyncStructureAfterEventArgs(before, ddl, exception); - _orm.Aop.SyncStructureAfter?.Invoke(this, after); - } - } - public ICodeFirst ConfigEntity(Action> entity) => _commonUtils.ConfigEntity(entity); - public ICodeFirst ConfigEntity(Type type, Action entity) => _commonUtils.ConfigEntity(type, entity); - public TableAttribute GetConfigEntity(Type type) => _commonUtils.GetConfigEntity(type); - public TableInfo GetTableByEntity(Type type) => _commonUtils.GetTableByEntity(type); } } \ No newline at end of file diff --git a/Providers/FreeSql.Provider.Sqlite/FreeSql.Provider.Sqlite.csproj b/Providers/FreeSql.Provider.Sqlite/FreeSql.Provider.Sqlite.csproj index c935571a..db52761c 100644 --- a/Providers/FreeSql.Provider.Sqlite/FreeSql.Provider.Sqlite.csproj +++ b/Providers/FreeSql.Provider.Sqlite/FreeSql.Provider.Sqlite.csproj @@ -2,7 +2,7 @@ netstandard2.0;net45 - 0.6.3 + 0.6.4 true YeXiangQin FreeSql 数据库实现,基于 Sqlite 3.0 diff --git a/Providers/FreeSql.Provider.Sqlite/SqliteCodeFirst.cs b/Providers/FreeSql.Provider.Sqlite/SqliteCodeFirst.cs index 930580e6..e3fdc8c5 100644 --- a/Providers/FreeSql.Provider.Sqlite/SqliteCodeFirst.cs +++ b/Providers/FreeSql.Provider.Sqlite/SqliteCodeFirst.cs @@ -12,22 +12,9 @@ using System.Text.RegularExpressions; namespace FreeSql.Sqlite { - class SqliteCodeFirst : ICodeFirst { - IFreeSql _orm; - protected CommonUtils _commonUtils; - protected CommonExpression _commonExpression; - public SqliteCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) { - _orm = orm; - _commonUtils = commonUtils; - _commonExpression = commonExpression; - } + class SqliteCodeFirst : Internal.CommonProvider.CodeFirstProvider { - public bool IsAutoSyncStructure { get; set; } = false; - public bool IsSyncStructureToLower { get; set; } = false; - public bool IsSyncStructureToUpper { get; set; } = false; - public bool IsConfigEntityFromDbFirst { get; set; } = false; - public bool IsNoneCommandParameter { get; set; } = false; - public bool IsLazyLoading { get; set; } = false; + public SqliteCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) : base(orm, commonUtils, commonExpression) { } static object _dicCsToDbLock = new object(); static Dictionary _dicCsToDb = new Dictionary() { @@ -56,7 +43,7 @@ namespace FreeSql.Sqlite { { typeof(Guid).FullName, (DbType.Guid, "character", "character(36) NOT NULL", false, false, Guid.Empty) },{ typeof(Guid?).FullName, (DbType.Guid, "character", "character(36)", false, true, null) }, }; - public (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { + public override (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) { if (_dicCsToDb.TryGetValue(type.FullName, out var trydc)) return new (int, string, string, bool?, object)?(((int)trydc.type, trydc.dbtype, trydc.dbtypeFull, trydc.isnullable, trydc.defaultValue)); if (type.IsArray) return null; var enumType = type.IsEnum ? type : null; @@ -75,9 +62,8 @@ namespace FreeSql.Sqlite { } return null; } - - public string GetComparisonDDLStatements() => this.GetComparisonDDLStatements(typeof(TEntity)); - public string GetComparisonDDLStatements(params Type[] entityTypes) { + + public override string GetComparisonDDLStatements(params Type[] entityTypes) { var sb = new StringBuilder(); var sbDeclare = new StringBuilder(); foreach (var entityType in entityTypes) { @@ -250,40 +236,5 @@ namespace FreeSql.Sqlite { return sb.Length == 0 ? null : sb.ToString(); } static Regex _regexUK = new Regex(@"CONSTRAINT\s*""([^""]+)""\s*UNIQUE\s*\(([^\)]+)\)", RegexOptions.IgnoreCase | RegexOptions.Compiled); - - static object syncStructureLock = new object(); - ConcurrentDictionary dicSyced = new ConcurrentDictionary(); - public bool SyncStructure() => this.SyncStructure(typeof(TEntity)); - public bool SyncStructure(params Type[] entityTypes) { - if (entityTypes == null) return true; - var syncTypes = entityTypes.Where(a => a.IsAnonymousType() == false && dicSyced.ContainsKey(a.FullName) == false).ToArray(); - if (syncTypes.Any() == false) return true; - var before = new Aop.SyncStructureBeforeEventArgs(entityTypes); - _orm.Aop.SyncStructureBefore?.Invoke(this, before); - Exception exception = null; - string ddl = null; - try { - lock (syncStructureLock) { - ddl = this.GetComparisonDDLStatements(syncTypes); - if (string.IsNullOrEmpty(ddl)) { - foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); - return true; - } - var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl); - foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true); - return affrows > 0; - } - } catch (Exception ex) { - exception = ex; - throw ex; - } finally { - var after = new Aop.SyncStructureAfterEventArgs(before, ddl, exception); - _orm.Aop.SyncStructureAfter?.Invoke(this, after); - } - } - public ICodeFirst ConfigEntity(Action> entity) => _commonUtils.ConfigEntity(entity); - public ICodeFirst ConfigEntity(Type type, Action entity) => _commonUtils.ConfigEntity(type, entity); - public TableAttribute GetConfigEntity(Type type) => _commonUtils.GetConfigEntity(type); - public TableInfo GetTableByEntity(Type type) => _commonUtils.GetTableByEntity(type); } } \ No newline at end of file diff --git a/readme.md b/readme.md index 280951da..9238f0b8 100644 --- a/readme.md +++ b/readme.md @@ -45,7 +45,7 @@ FreeSql 是一个功能强大的 .NETStandard 库,用于对象关系映射程 | FreeSql.Provider.SqlServer | NETStandard2.0、net451 | | FreeSql.Provider.Sqlite | NETStandard2.0、net45 | | FreeSql.Provider.Oracle | NETStandard2.0、net45 | -| FreeSql.Extensions.LazyLoading | NETStandard2.0 | +| FreeSql.Extensions.LazyLoading | NETStandard2.0、net45 | # Quick start