From 4fe8d44e8ce48aa53b2ee9a0d9ddb69ddfbafd0b Mon Sep 17 00:00:00 2001 From: MaceWindu Date: Thu, 3 Oct 2019 11:33:52 +0200 Subject: [PATCH 1/2] - update dependencies - add 'disable FKs' option --- Source/ConnectionDialog.xaml | 1 + Source/ConnectionViewModel.generated.cs | 37 ++++++ Source/ConnectionViewModel.tt | 1 + Source/DriverHelper.cs | 3 +- Source/SchemaAndCodeGenerator.cs | 5 +- Source/SchemaGenerator.cs | 151 ------------------------ Source/linq2db.LINQPad.csproj | 20 ++-- appveyor.yml | 8 +- 8 files changed, 58 insertions(+), 168 deletions(-) diff --git a/Source/ConnectionDialog.xaml b/Source/ConnectionDialog.xaml index 7e2bf97..d815984 100644 --- a/Source/ConnectionDialog.xaml +++ b/Source/ConnectionDialog.xaml @@ -146,6 +146,7 @@ + diff --git a/Source/ConnectionViewModel.generated.cs b/Source/ConnectionViewModel.generated.cs index 8563052..8af3680 100644 --- a/Source/ConnectionViewModel.generated.cs +++ b/Source/ConnectionViewModel.generated.cs @@ -346,6 +346,43 @@ private void OnIncludeRoutinesChanged() #endregion + #region IncludeFKs : bool + + private bool _includeFKs; + public bool IncludeFKs + { + get { return _includeFKs; } + set + { + if (_includeFKs != value) + { + BeforeIncludeFKsChanged(value); + _includeFKs = value; + AfterIncludeFKsChanged(); + + OnIncludeFKsChanged(); + } + } + } + + #region INotifyPropertyChanged support + + partial void BeforeIncludeFKsChanged(bool newValue); + partial void AfterIncludeFKsChanged (); + + public const string NameOfIncludeFKs = "IncludeFKs"; + + private static readonly PropertyChangedEventArgs _includeFKsChangedEventArgs = new PropertyChangedEventArgs(NameOfIncludeFKs); + + private void OnIncludeFKsChanged() + { + OnPropertyChanged(_includeFKsChangedEventArgs); + } + + #endregion + + #endregion + #region EncryptConnectionString : bool private bool _encryptConnectionString; diff --git a/Source/ConnectionViewModel.tt b/Source/ConnectionViewModel.tt index 0d95e66..2bc2fa2 100644 --- a/Source/ConnectionViewModel.tt +++ b/Source/ConnectionViewModel.tt @@ -19,6 +19,7 @@ new NotifyingProperty("bool", "Pluralize"), new NotifyingProperty("bool", "Capitalize"), new NotifyingProperty("bool", "IncludeRoutines"), + new NotifyingProperty("bool", "IncludeFKs"), new NotifyingProperty("bool", "EncryptConnectionString"), new NotifyingProperty("bool", "UseCustomFormatter"), new NotifyingProperty("bool", "UseProviderSpecificTypes"), diff --git a/Source/DriverHelper.cs b/Source/DriverHelper.cs index 2de98e8..472c23a 100644 --- a/Source/DriverHelper.cs +++ b/Source/DriverHelper.cs @@ -39,8 +39,8 @@ public static bool ShowConnectionDialog(DataContextDriver driver, IConnectionInf model.EncryptConnectionString = cxInfo.DatabaseInfo.EncryptCustomCxString; model.Pluralize = !cxInfo.DynamicSchemaOptions.NoPluralization; model.Capitalize = !cxInfo.DynamicSchemaOptions.NoCapitalization; - //model.IncludeRoutines = !isNewConnection && !cxInfo.DynamicSchemaOptions.ExcludeRoutines; model.IncludeRoutines = cxInfo.DriverData.Element("excludeRoutines")?.Value.ToLower() != "true"; + model.IncludeFKs = cxInfo.DriverData.Element("excludeFKs")?.Value.ToLower() != "true"; model.ConnectionString = cxInfo.DatabaseInfo.CustomCxString.IsNullOrWhiteSpace() ? (string)cxInfo.DriverData.Element("connectionString") : cxInfo.DatabaseInfo.CustomCxString; model.IncludeSchemas = cxInfo.DriverData.Element("includeSchemas") ?.Value; model.ExcludeSchemas = cxInfo.DriverData.Element("excludeSchemas") ?.Value; @@ -61,6 +61,7 @@ public static bool ShowConnectionDialog(DataContextDriver driver, IConnectionInf cxInfo.DriverData.SetElementValue("providerName", providerName); cxInfo.DriverData.SetElementValue("connectionString", null); cxInfo.DriverData.SetElementValue("excludeRoutines", !model.IncludeRoutines ? "true" : "false"); + cxInfo.DriverData.SetElementValue("excludeFKs", !model.IncludeFKs ? "true" : "false"); cxInfo.DriverData.SetElementValue("includeSchemas", model.IncludeSchemas. IsNullOrWhiteSpace() ? null : model.IncludeSchemas); cxInfo.DriverData.SetElementValue("excludeSchemas", model.ExcludeSchemas. IsNullOrWhiteSpace() ? null : model.ExcludeSchemas); cxInfo.DriverData.SetElementValue("includeCatalogs", model.IncludeCatalogs.IsNullOrWhiteSpace() ? null : model.IncludeSchemas); diff --git a/Source/SchemaAndCodeGenerator.cs b/Source/SchemaAndCodeGenerator.cs index ffac7b4..cd07d9a 100644 --- a/Source/SchemaAndCodeGenerator.cs +++ b/Source/SchemaAndCodeGenerator.cs @@ -60,7 +60,7 @@ public IEnumerable GetItemsAndCode(string nameSpace, string typeNa db.CommandTimeout = CommandTimeout; _dataProvider = db.DataProvider; - _sqlBuilder = _dataProvider.CreateSqlBuilder(); + _sqlBuilder = _dataProvider.CreateSqlBuilder(_dataProvider.MappingSchema); var options = new GetSchemaOptions(); @@ -76,7 +76,8 @@ public IEnumerable GetItemsAndCode(string nameSpace, string typeNa var excludeCatalogs = (string)_cxInfo.DriverData.Element("excludeCatalogs"); if (excludeCatalogs != null) options.ExcludedCatalogs = excludeCatalogs.Split(',', ';'); - options.GetProcedures = (string)_cxInfo.DriverData.Element("excludeRoutines") != "true"; + options.GetProcedures = (string)_cxInfo.DriverData.Element("excludeRoutines") != "true"; + options.GetForeignKeys = (string)_cxInfo.DriverData.Element("excludeFKs") != "true"; _schema = _dataProvider.GetSchemaProvider().GetSchema(db, options); diff --git a/Source/SchemaGenerator.cs b/Source/SchemaGenerator.cs index f4b5309..bd3cb01 100644 --- a/Source/SchemaGenerator.cs +++ b/Source/SchemaGenerator.cs @@ -184,156 +184,5 @@ string GetTypeName(Type type) return type.Name; } - - /*public IEnumerable GetItemsAndCode(string nameSpace, string typeName) - { - var schemas = - ( - from t in - ( - from t in _schema.Tables - select new { t.IsDefaultSchema, t.SchemaName, Table = t, Procedure = (ProcedureSchema)null } - ) - .Union - ( - from p in _schema.Procedures - select new { p.IsDefaultSchema, p.SchemaName, Table = (TableSchema)null, Procedure = p } - ) - group t by new { t.IsDefaultSchema, t.SchemaName } into gr - orderby !gr.Key.IsDefaultSchema, gr.Key.SchemaName - select new - { - gr.Key, - Tables = gr.Where(t => t.Table != null).Select(t => t.Table). ToList(), - Procedures = gr.Where(t => t.Procedure != null).Select(t => t.Procedure).ToList(), - } - ) - .ToList(); - - foreach (var s in schemas) - { - var items = new List(); - - if (s.Tables.Any(t => !t.IsView && !t.IsProcedureResult)) - items.Add(GetTables("Tables", ExplorerIcon.Table, s.Tables.Where(t => !t.IsView && !t.IsProcedureResult))); - - if (s.Tables.Any(t => t.IsView)) - items.Add(GetTables("Views", ExplorerIcon.View, s.Tables.Where(t => t.IsView))); - - if (!_cxInfo.DynamicSchemaOptions.ExcludeRoutines && s.Procedures.Any(p => p.IsLoaded && !p.IsFunction)) - items.Add(GetProcedures( - "Stored Procs", - ExplorerIcon.StoredProc, - s.Procedures.Where(p => p.IsLoaded && !p.IsFunction).ToList())); - - if (s.Procedures.Any(p => p.IsLoaded && p.IsTableFunction)) - items.Add(GetProcedures( - "Table Functions", - ExplorerIcon.TableFunction, - s.Procedures.Where(p => p.IsLoaded && p.IsTableFunction).ToList())); - - if (s.Procedures.Any(p => p.IsFunction && !p.IsTableFunction)) - items.Add(GetProcedures( - "Scalar Functions", - ExplorerIcon.ScalarFunction, - s.Procedures.Where(p => p.IsFunction && !p.IsTableFunction).ToList())); - - if (schemas.Count == 1) - { - foreach (var item in items) - yield return item; - } - else - { - yield return new ExplorerItem( - s.Key.SchemaName.IsNullOrEmpty() ? s.Key.IsDefaultSchema ? "(default)" : "empty" : s.Key.SchemaName, - ExplorerItemKind.Schema, - ExplorerIcon.Schema) - { - Children = items - }; - } - } - } - - ExplorerItem GetColumnItem(ColumnSchema column) - { - var memberType = UseProviderSpecificTypes ? (column.ProviderSpecificType ?? column.MemberType) : column.MemberType; - var sqlName = (string)_sqlBuilder.Convert(column.ColumnName, ConvertType.NameToQueryField); - - return new ExplorerItem( - column.MemberName, - ExplorerItemKind.Property, - column.IsPrimaryKey ? ExplorerIcon.Key : ExplorerIcon.Column) - { - Text = $"{column.MemberName} : {memberType}", - ToolTipText = $"{sqlName} {column.ColumnType} {(column.IsNullable ? "NULL" : "NOT NULL")}{(column.IsIdentity ? " IDENTITY" : "")}", - DragText = column.MemberName, - SqlName = sqlName, - SqlTypeDeclaration = $"{column.ColumnType} {(column.IsNullable ? "NULL" : "NOT NULL")}{(column.IsIdentity ? " IDENTITY" : "")}", - }; - } - - ExplorerItem GetProcedures(string header, ExplorerIcon icon, List procedures) - { - var results = new HashSet(); - - var items = new ExplorerItem(header, ExplorerItemKind.Category, icon) - { - Children = procedures - .Select(p => - { - var sprocSqlName = _sqlBuilder.BuildTableName( - new StringBuilder(), - null, - p.SchemaName == null ? null : (string)_sqlBuilder.Convert(p.SchemaName, ConvertType.NameToOwner), - (string)_sqlBuilder.Convert(p.ProcedureName, ConvertType.NameToQueryTable)).ToString(); - - var memberName = p.MemberName; - - if (p.IsFunction && !p.IsTableFunction) - { - var res = p.Parameters.FirstOrDefault(pr => pr.IsResult); - - if (res != null) - memberName += $" -> {res.ParameterType}"; - } - - var ret = new ExplorerItem(memberName, ExplorerItemKind.QueryableObject, icon) - { - DragText = $"{p.MemberName}(" + - p.Parameters - .Where (pr => !pr.IsResult) - .Select(pr => $"{(pr.IsOut ? pr.IsIn ? "ref " : "out " : "")}{pr.ParameterName}") - .Join(", ") + - ")", - SqlName = sprocSqlName, - IsEnumerable = p.ResultTable != null, - Children = p.Parameters - .Where (pr => !pr.IsResult) - .Select(pr => - new ExplorerItem( - $"{pr.ParameterName} ({pr.ParameterType})", - ExplorerItemKind.Parameter, - ExplorerIcon.Parameter)) - .Union(p.ResultTable?.Columns.Select(GetColumnItem) ?? new ExplorerItem[0]) - .ToList(), - }; - - if (p.ResultTable != null && !results.Contains(p.ResultTable)) - { - results.Add(p.ResultTable); - } - - return ret; - }) - .OrderBy(p => p.Text) - .ToList(), - }; - - return items; - } - - */ } } diff --git a/Source/linq2db.LINQPad.csproj b/Source/linq2db.LINQPad.csproj index a79def9..b4603bf 100644 --- a/Source/linq2db.LINQPad.csproj +++ b/Source/linq2db.LINQPad.csproj @@ -16,18 +16,18 @@ - - - - - - + + + + + + - - - - + + + + diff --git a/appveyor.yml b/appveyor.yml index db3c211..635becb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,12 +1,12 @@ -version: 2.7.0.{build} +version: 2.8.0.{build} os: Visual Studio 2017 configuration: Release assembly_info: patch: true file: '**\AssemblyInfo.*' - assembly_version: '2.7.0' - assembly_file_version: '2.7.0' - assembly_informational_version: '2.7.0' + assembly_version: '2.8.0' + assembly_file_version: '2.8.0' + assembly_informational_version: '2.8.0' before_build: - cmd: nuget restore build: From e68a8018b93158ecd916409ad767a0aa0b4bb693 Mon Sep 17 00:00:00 2001 From: MaceWindu Date: Thu, 3 Oct 2019 12:48:56 +0200 Subject: [PATCH 2/2] migrate procedure return value support https://github.com/linq2db/linq2db/pull/1905 --- Source/SchemaAndCodeGenerator.cs | 49 +++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/Source/SchemaAndCodeGenerator.cs b/Source/SchemaAndCodeGenerator.cs index cd07d9a..2e62c07 100644 --- a/Source/SchemaAndCodeGenerator.cs +++ b/Source/SchemaAndCodeGenerator.cs @@ -275,8 +275,8 @@ void CodeProcedure(StringBuilder code, ProcedureSchema p, string sprocSqlName) code .Append($" {p.MemberName}(") .Append(p.Parameters - .Where (pr => !pr.IsResult) - .Select(pr => $"{(pr.IsOut ? pr.IsIn ? "ref " : "out " : "")}{pr.ParameterType} {pr.ParameterName}") + .Where (pr => !pr.IsResult || !p.IsFunction) + .Select(pr => $"{(pr.IsOut || pr.IsResult ? pr.IsIn ? "ref " : "out " : "")}{pr.ParameterType} {pr.ParameterName}") .Join(", ")) .AppendLine(")") .AppendLine(" {") @@ -294,13 +294,14 @@ void CodeProcedure(StringBuilder code, ProcedureSchema p, string sprocSqlName) } else if (p.IsFunction) { + // aggregate and scalar functions branch code.AppendLine(" throw new InvalidOperationException();"); } else { - var inputParameters = p.Parameters.Where(pp => pp.IsIn) .ToList(); - var outputParameters = p.Parameters.Where(pp => pp.IsOut) .ToList(); - var inOrOutputParameters = p.Parameters.Where(pp => pp.IsIn || pp.IsOut).ToList(); + var inputParameters = p.Parameters.Where(pp => pp.IsIn) .ToList(); + var outputParameters = p.Parameters.Where(pp => pp.IsOut || pp.IsResult) .ToList(); + var inOrOutputParameters = p.Parameters.Where(pp => pp.IsIn || pp.IsOut || pp.IsResult).ToList(); spName += inOrOutputParameters.Count == 0 ? ");" : ","; @@ -310,7 +311,7 @@ void CodeProcedure(StringBuilder code, ProcedureSchema p, string sprocSqlName) while (p.Parameters.Any(pp => pp.ParameterName == retName)) retName = "__ret__" + ++retNo; - var hasOut = outputParameters.Any(pr => pr.IsOut); + var hasOut = outputParameters.Any(pr => pr.IsOut || pr.IsResult); var prefix = hasOut ? $"var {retName} =" : "return"; if (p.ResultTable == null) @@ -361,16 +362,16 @@ void CodeProcedure(StringBuilder code, ProcedureSchema p, string sprocSqlName) var pr = inOrOutputParameters[i]; var str = string.Format( - !pr.IsIn && pr.IsOut + !pr.IsIn && (pr.IsOut || pr.IsResult) ? " new DataParameter({0}, null, DataType.{2})" : " new DataParameter({0}, {1}, DataType.{2})", CSharpTools.ToStringLiteral(pr.SchemaName), pr.ParameterName, pr.DataType); - if (pr.IsOut) + if (pr.IsOut || pr.IsResult) { - str += " { Direction = " + (pr.IsIn ? "ParameterDirection.InputOutput" : "ParameterDirection.Output"); + str += " { Direction = " + (pr.IsIn ? "ParameterDirection.InputOutput" : (pr.IsResult ? "ParameterDirection.ReturnValue" : "ParameterDirection.Output")); if (pr.Size != null && pr.Size.Value != 0) str += ", Size = " + pr.Size.Value; @@ -389,7 +390,7 @@ void CodeProcedure(StringBuilder code, ProcedureSchema p, string sprocSqlName) { code.AppendLine(); - foreach (var pr in p.Parameters.Where(_ => _.IsOut)) + foreach (var pr in p.Parameters.Where(_ => _.IsOut || _.IsResult)) { var str = $" {pr.ParameterName} = Converter.ChangeTypeTo<{pr.ParameterType}>(((IDbDataParameter)this.Command.Parameters[\"{pr.SchemaName}\"]).Value);"; code.AppendLine(str); @@ -452,14 +453,14 @@ ExplorerItem GetProcedures(string header, ExplorerIcon icon, List !pr.IsResult) - .Select(pr => $"{(pr.IsOut ? pr.IsIn ? "ref " : "out " : "")}{pr.ParameterName}") + .Where (pr => !pr.IsResult || !p.IsFunction) + .Select(pr => $"{(pr.IsOut || pr.IsResult ? (pr.IsIn ? "ref " : "out ") : "")}{pr.ParameterName}") .Join(", ") + ")", SqlName = sprocSqlName, IsEnumerable = p.ResultTable != null, Children = p.Parameters - .Where (pr => !pr.IsResult) + .Where (pr => !pr.IsResult || !p.IsFunction) .Select(pr => new ExplorerItem( $"{pr.ParameterName} ({pr.ParameterType})", @@ -697,6 +698,28 @@ void ConvertSchema(string typeName) foreach (var procedure in _schema.Procedures) { + // migrate https://github.com/linq2db/linq2db/pull/1905 + if (!procedure.IsFunction && ProviderName == LinqToDB.ProviderName.SqlServer) + { + // sql server procedures always have integer return parameter + var name = "@returnValue"; + var cnt = 0; + while (procedure.Parameters.Any(_ => _.ParameterName == name)) + name = $"@returnValue{cnt++}"; + + procedure.Parameters.Add(new ParameterSchema() + { + SchemaName = name, + ParameterName = name, + IsResult = true, + DataType = DataType.Int32, + SystemType = typeof(int), + SchemaType = "int", + ParameterType = "int", + ProviderSpecificType = "int" + }); + } + procedure.MemberName = GetName(typeNames, procedure.MemberName); if (procedure.ResultTable != null && !_contextMembers.ContainsKey(procedure.ResultTable))