Skip to content

Issue #2796 View Column type enumeration work around #2798

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 86 additions & 1 deletion src/Core/NUnitTestCore/Dacpac/DacpacTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,85 @@ namespace UnitTests
public class DacpacTest
{
private string dacpac;

private string dacpacViews;
private string dacpacQuirk;

[SetUp]
public void Setup()
{
dacpacQuirk = TestPath("TestDb.dacpac");
dacpac = TestPath("Chinook.dacpac");
dacpacViews = TestPath("ViewColumnTypesSqlProj.dacpac");
#region Here Is the SQL used to create ViewColumnTypesSqlProj.dacpac
/*
CREATE VIEW [dbo].[AllTypes]
AS

SELECT
CAST( 0x1 AS bit ) col_bit
,CAST( 0x2 AS tinyint ) col_tinyint
,CAST( 0x3 AS smallint ) col_smallint
,CAST( 0x4 AS int ) col_int
,CAST( 0x5 AS bigint ) col_bigint
,CAST( 6 AS decimal ) col_decimal
,CAST( 7 AS numeric ) col_numeric
,CAST( 8 AS money ) col_money
,CAST( 9 AS smallmoney ) col_smallmoney
,CAST( 10 AS float ) col_float
,CAST( 11 AS real ) col_real
,CAST( '12/12/12' AS date ) col_date
,CAST( '13:13' AS time ) col_time
,CAST( '12/14/2014 14:14' AS datetime2 ) col_datetime2
,CAST( '12/15/2015 15:15' AS datetimeoffset ) col_datetimeoffset
,CAST( '12/16/2016 16:16' AS datetime ) col_datetime
,CAST( '12/17/17' AS smalldatetime ) col_smalldatetime
,CAST( 0x18 AS varchar(1) ) col_varchar
,CAST( '19' AS text ) col_text
,CAST( 0x20 AS nchar ) col_nchar
,CAST( 0x21 AS nvarchar(1) ) col_nvarchar
,CAST( '22' AS ntext ) col_ntext
,CAST( 0x23 AS binary ) col_binary
,CAST( 0x24 AS varbinary(1) ) col_varbinary
,CAST( 0x25 AS image ) col_image
,CAST( 0x26 AS rowversion ) col_rowversion
,CAST( 0x27 AS uniqueidentifier ) col_uniqueidentifier
,CAST( '<root>28</root>' AS xml ) col_xml

GO

CREATE TYPE [dbo].[AllTypes] AS TABLE (
[col_bit] [bit] NULL,
[col_tinyint] [tinyint] NULL,
[col_smallint] [smallint] NULL,
[col_int] [int] NULL,
[col_bigint] [bigint] NULL,
[col_decimal] [decimal](18, 0) NULL,
[col_numeric] [numeric](18, 0) NULL,
[col_money] [money] NULL,
[col_smallmoney] [smallmoney] NULL,
[col_float] [float] NULL,
[col_real] [real] NULL,
[col_date] [date] NULL,
[col_time] [time](7) NULL,
[col_datetime2] [datetime2](7) NULL,
[col_datetimeoffset] [datetimeoffset](7) NULL,
[col_datetime] [datetime] NULL,
[col_smalldatetime] [smalldatetime] NULL,
[col_varchar] [varchar](1) NULL,
[col_text] [text] NULL,
[col_nchar] [nchar](30) NULL,
[col_nvarchar] [nvarchar](1) NULL,
[col_ntext] [ntext] NULL,
[col_binary] [binary](30) NULL,
[col_varbinary] [varbinary](1) NULL,
[col_image] [image] NULL,
[col_rowversion] [timestamp] NULL,
[col_uniqueidentifier] [uniqueidentifier] NULL,
[col_xml] [xml] NULL
)
GO
*/
#endregion
}

[Test]
Expand All @@ -37,6 +108,20 @@ public void CanEnumerateTables()
Assert.AreEqual(11, dbModel.Tables.Count());
}

[Test]
public void CanEnumerateViewColumns()
{
// Arrange
var factory = new SqlServerDacpacDatabaseModelFactory();
var options = new DatabaseModelFactoryOptions(new List<string>(), new List<string>());

// Act
var dbModel = factory.Create(dacpacViews, options);

// Assert
Assert.AreEqual(28, dbModel.Tables[0].Columns.Count());
}

[Test]
public void CanEnumerateSelectedTables()
{
Expand Down
Binary file not shown.
5 changes: 5 additions & 0 deletions src/Core/NUnitTestCore/NUnitTestCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -104,5 +104,10 @@
<ProjectReference Include="..\..\Nupkg\ErikEJ.EntityFrameworkCore.DgmlBuilder\ErikEJ.EntityFrameworkCore.DgmlBuilder.csproj" />
<ProjectReference Include="..\RevEng.Core.80\RevEng.Core.80.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="Dacpac\ViewColumnTypesSqlProj.dacpac">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ public DatabaseModel Create(string connectionString, DatabaseModelFactoryOptions
.Where(t => tables == null || !tables.Any() || tables.Contains($"[{t.Name.Parts[0]}].[{t.Name.Parts[1]}]"))
.ToList();

var tableTypes = model.GetObjects<TSqlTableType>(DacQueryScopes.UserDefined);

foreach (var view in views)
{
var dbView = new DatabaseView
Expand All @@ -174,7 +176,7 @@ public DatabaseModel Create(string connectionString, DatabaseModelFactoryOptions
Schema = view.Name.Parts[0],
};

GetViewColumns(view, dbView, typeAliases);
GetViewColumns(view, dbView, typeAliases, tableTypes);

dbModel.Tables.Add(dbView);
}
Expand Down Expand Up @@ -297,15 +299,18 @@ private static void GetTriggers(TSqlTable table, DatabaseTable dbTable)
}
}

private static void GetViewColumns(TSqlView item, DatabaseView dbTable, Dictionary<string, (string StoreType, string TypeName)> typeAliases)
private static void GetViewColumns(TSqlView item, DatabaseView dbTable, Dictionary<string, (string StoreType, string TypeName)> typeAliases, IEnumerable<TSqlTableType> tableTypes)
{
var viewColumns = item.Element.GetChildren(DacQueryScopes.UserDefined);

var matchingTableType = tableTypes.FirstOrDefault(tt => tt.Name.ToString() == item.Name.ToString()
&& tt.Columns.All(ttc => viewColumns.Any(vc => vc.Name.ToString() == ttc.Name.ToString()))); // All Column Names of Table Type are also in View

foreach (var column in viewColumns)
{
string storeType = null;

var referenced = column.GetReferenced(DacQueryScopes.UserDefined).FirstOrDefault();
var referenced = column.GetReferenced(DacQueryScopes.UserDefined).FirstOrDefault() ?? column;

if (referenced == null)
{
Expand All @@ -321,10 +326,23 @@ private static void GetViewColumns(TSqlView item, DatabaseView dbTable, Dictiona

if (col.ColumnType == ColumnType.ComputedColumn)
{
continue;
}
if (matchingTableType == null)
{
continue;
}

if (col.DataType.First().Name.Parts.Count > 1)
var matchingColumn = matchingTableType.Columns.FirstOrDefault(c => c.Name.ToString() == col.Name.ToString());

if (matchingColumn == null)
{
continue;
}

var dataTypeName = matchingColumn.DataType.First().Name.Parts[0];
int maxLength = matchingColumn.IsMax ? -1 : matchingColumn.Length;
storeType = GetStoreType(dataTypeName, maxLength, matchingColumn.Precision, matchingColumn.Scale);
}
else if (col.DataType.First().Name.Parts.Count > 1)
{
if (typeAliases.TryGetValue($"{col.DataType.First().Name.Parts[0]}.{col.DataType.First().Name.Parts[1]}", out var value))
{
Expand Down