diff --git a/readme.md b/readme.md
index 735b2be..66fa304 100644
--- a/readme.md
+++ b/readme.md
@@ -50,7 +50,7 @@ This test:
```cs
await Verify(connection);
```
-snippet source | anchor
+snippet source | anchor
Will result in the following verified file:
@@ -69,7 +69,7 @@ await Verify(connection)
// include only tables and views
.SchemaIncludes(DbObjects.Tables | DbObjects.Views);
```
-snippet source | anchor
+snippet source | anchor
Available values:
@@ -107,7 +107,7 @@ await Verify(connection)
_ => _ is TableViewBase ||
_.Name == "MyTrigger");
```
-snippet source | anchor
+snippet source | anchor
@@ -129,7 +129,7 @@ command.CommandText = "select Value from MyTable";
var value = await command.ExecuteScalarAsync();
await Verify(value!);
```
-snippet source | anchor
+snippet source | anchor
Will result in the following verified file:
@@ -184,7 +184,7 @@ await Verify(
sqlEntries = entries
});
```
-snippet source | anchor
+snippet source | anchor
@@ -212,7 +212,7 @@ var sqlErrorsViaType = entries
.Select(_ => _.Data)
.OfType();
```
-snippet source | anchor
+snippet source | anchor
diff --git a/src/Tests/Tests.SchemaFromOpenConnection.verified.md b/src/Tests/Tests.SchemaFromOpenConnection.verified.md
new file mode 100644
index 0000000..a057690
--- /dev/null
+++ b/src/Tests/Tests.SchemaFromOpenConnection.verified.md
@@ -0,0 +1,21 @@
+## Tables
+
+### MyTable
+
+```sql
+CREATE TABLE [dbo].[MyTable](
+ [Value] [int] NULL
+) ON [PRIMARY]
+
+CREATE NONCLUSTERED INDEX [MyIndex] ON [dbo].[MyTable]
+(
+ [Value] ASC
+) ON [PRIMARY]
+
+CREATE TRIGGER MyTrigger
+ON MyTable
+AFTER UPDATE
+AS RAISERROR ('Notify Customer Relations', 16, 10);
+
+ALTER TABLE [dbo].[MyTable] ENABLE TRIGGER [MyTrigger]
+```
diff --git a/src/Tests/Tests.cs b/src/Tests/Tests.cs
index 440c9c3..ad9c378 100644
--- a/src/Tests/Tests.cs
+++ b/src/Tests/Tests.cs
@@ -8,10 +8,9 @@ static Tests() =>
"VerifySqlServer",
connection =>
{
- var serverConnection = new ServerConnection
- {
- ConnectionString = connection.ConnectionString,
- };
+ var serverConnection = new ServerConnection();
+ SqlScriptBuilder.SqlConnectionObjectField.SetValue(serverConnection, connection);
+ serverConnection.NonPooledConnection = true;
var server = new Server(serverConnection);
server.ConnectionContext.ExecuteNonQuery(
"""
@@ -854,4 +853,19 @@ await Verify(connection)
.SchemaIncludes(DbObjects.Tables | DbObjects.Views)
.SchemaFilter(_ => _.Name is "MyTable" or "MyView" or "MyProcedure");
}
-}
\ No newline at end of file
+
+ // Verifies the workaround for SMO 181.15.0 + SqlClient 7.0 TypeLoadException.
+ // SMO's ServerConnection(SqlConnection) constructor references SqlAuthenticationMethod
+ // which moved from Microsoft.Data.SqlClient to Extensions.Abstractions in SqlClient 7.0.
+ // The fix avoids that constructor by using reflection to set the SqlConnection directly.
+ [Test]
+ public async Task SchemaFromOpenConnection()
+ {
+ await using var database = await sqlInstance.Build();
+ await using var connection = new SqlConnection(database.ConnectionString);
+ await connection.OpenAsync();
+ await Verify(connection)
+ .SchemaFilter(_ => _.Name == "MyTable")
+ .SchemaIncludes(DbObjects.Tables);
+ }
+}
diff --git a/src/Verify.SqlServer/GlobalUsings.cs b/src/Verify.SqlServer/GlobalUsings.cs
index 9ad4469..4af539c 100644
--- a/src/Verify.SqlServer/GlobalUsings.cs
+++ b/src/Verify.SqlServer/GlobalUsings.cs
@@ -2,8 +2,10 @@
global using System.Data.Common;
global using System.Data.SqlTypes;
global using System.Globalization;
+global using System.Text.RegularExpressions;
global using Microsoft.Data.SqlClient;
global using Microsoft.Extensions.DiagnosticAdapter;
global using Microsoft.SqlServer.Management.Common;
+global using Microsoft.SqlServer.Management.Smo;
global using Microsoft.SqlServer.TransactSql.ScriptDom;
global using VerifyTests.SqlServer;
\ No newline at end of file
diff --git a/src/Verify.SqlServer/SchemaValidation/SchemaSettings.cs b/src/Verify.SqlServer/SchemaValidation/SchemaSettings.cs
index bc1348b..7ffe213 100644
--- a/src/Verify.SqlServer/SchemaValidation/SchemaSettings.cs
+++ b/src/Verify.SqlServer/SchemaValidation/SchemaSettings.cs
@@ -1,5 +1,3 @@
-using Microsoft.SqlServer.Management.Smo;
-
class SchemaSettings
{
public DbObjects Includes { get; set; } = DbObjects.All;
diff --git a/src/Verify.SqlServer/SchemaValidation/SqlScriptBuilder.cs b/src/Verify.SqlServer/SchemaValidation/SqlScriptBuilder.cs
index dcb9ef2..4a26f17 100644
--- a/src/Verify.SqlServer/SchemaValidation/SqlScriptBuilder.cs
+++ b/src/Verify.SqlServer/SchemaValidation/SqlScriptBuilder.cs
@@ -1,8 +1,20 @@
-using System.Text.RegularExpressions;
-using Microsoft.SqlServer.Management.Smo;
-
class SqlScriptBuilder(SchemaSettings settings)
{
+ // TODO: when Microsoft.Data.SqlClient 7.0.1 adds TypeForwardedTo for SqlAuthenticationMethod,
+ // revert to using new ServerConnection(SqlConnection) and remove this reflection workaround.
+ //
+ // SMO 181.15.0 ServerConnection(SqlConnection) constructor calls InitFromSqlConnection
+ // which references SqlAuthenticationMethod — a type moved from Microsoft.Data.SqlClient
+ // to Microsoft.Data.SqlClient.Extensions.Abstractions in SqlClient 7.0. The CLR can't
+ // resolve the type in the original assembly, causing a TypeLoadException.
+ //
+ // Workaround: construct ServerConnection() with default constructor (no InitFromSqlConnection),
+ // then set the internal m_SqlConnectionObject field via reflection to reuse the open connection.
+ // SMO detects the connection is already open and uses it directly.
+ internal static readonly FieldInfo SqlConnectionObjectField =
+ typeof(ConnectionManager).GetField("m_SqlConnectionObject", BindingFlags.NonPublic | BindingFlags.Instance) ??
+ throw new("Could not find field m_SqlConnectionObject on ConnectionManager. The SMO internals may have changed.");
+
static Dictionary tableSettingsToScrubLookup;
static SqlScriptBuilder()
@@ -33,10 +45,12 @@ public string BuildContent(SqlConnection connection)
var builder = new SqlConnectionStringBuilder(connection.ConnectionString);
var serverConnection = new ServerConnection
{
+ NonPooledConnection = true,
ConnectionString = connection.ConnectionString,
};
try
{
+ SqlConnectionObjectField.SetValue(serverConnection, connection);
var server = new Server(serverConnection);
return BuildContent(server, builder);
}
@@ -240,4 +254,4 @@ script is
"SET QUOTED_IDENTIFIER OFF" or
"SET ANSI_PADDING ON" or
"SET ANSI_PADDING OFF";
-}
\ No newline at end of file
+}
diff --git a/src/Verify.SqlServer/SchemaValidation/VerifySettingsExtensions.cs b/src/Verify.SqlServer/SchemaValidation/VerifySettingsExtensions.cs
index 9fcf0e3..038bb59 100644
--- a/src/Verify.SqlServer/SchemaValidation/VerifySettingsExtensions.cs
+++ b/src/Verify.SqlServer/SchemaValidation/VerifySettingsExtensions.cs
@@ -1,5 +1,3 @@
-using Microsoft.SqlServer.Management.Smo;
-
namespace VerifyTests;
public static partial class VerifySettingsSqlExtensions
@@ -81,4 +79,4 @@ internal static SchemaSettings GetSchemaSettings(this IReadOnlyDictionarynet48;net8.0;net9.0;net10.0
+