CREATE ASSEMBLY in SQLCLR using assembly byte stri

2019-09-01 04:55发布

问题:

I am trying to add user-defined aggregates to a SQL Server 2008 database whose schema is defined in my Visual Studio 2010 solution file. The code for this custom aggregate lives in a SQLCLR project within the same solution, but I am having a lot of difficulty getting my unit tests to pass. For unit testing this project, I am using a method similar to the one here to get the byte string of the assembly. The test suite or a post-build event needs to automatically update my script to create the assembly each time, because after any sort of MSBuild (from the command line or Visual Studio), the assembly bits change.

The script seems to be updating its assembly bit string to correctly match the current assembly bits for each run. But the unit test still fails, with an underlying SQLException saying, "CREATE ASSEMBLY failed because it could not open the physical file "0xDEADBEEF": 3(The system cannot find the path specified.). (I've removed the real assembly bits from that message.) Why would this error come up when the assembly bits appear to be correct? How should I fix this?

The length of the actual assembly bit string is about 16 KB. Would this be a problem? Does CREATE ASSEMBLY need to have the bits for the whole assembly or just a header, and how would I get only the header?

We already have the unit test infrastructure in place to deploy this database, including running pre- and post-deployment scripts. We also have an authorization set up that our user-defined functions and aggregates need to have.

Here is my post-deployment script:

IF EXISTS (SELECT name FROM sys.assemblies WHERE name = 'foo')
   DROP ASSEMBLY foo
go

-- The assembly bits change after every build from the command line or Visual Studio.  
-- This variable needs to change each time the foo assembly changes.
declare @assemblyBits as varchar(max)
-- This string is really about 15000 characters, including some newlines which are removed
-- in the next block.  Word-wrapping this line or not word-wrapping it seems to have no 
-- effect.
set @assemblyBits = '0x42'

-- Trim whitespace from assembly bits.
declare @sanitizedBits as varchar(max)
set @sanitizedBits = Replace(Replace(Replace(@assemblyBits, Char(10), ''), Char(13), ''), Char(9), '')

CREATE ASSEMBLY foo
AUTHORIZATION bar
from @sanitizedBits 
GO

IF EXISTS (SELECT name FROM sysobjects WHERE name = 'Product')
   DROP AGGREGATE Product
go

CREATE AGGREGATE [Aggregations].[Product]
    (@value float,
    @weight float)
    RETURNS float
    EXTERNAL NAME foo.[foo.Product]
go

回答1:

use dynamic sql if you have the content as a string

    EXEC ('CREATE ASSEMBLY foo AUTHORIZATION bar from ' + @sanitizedBits )

Normally you pass in a varbinary



回答2:

Try executing the Create Assembly code on the remote Server, on which the database is hosted. It should solve the problem.