2017-01-06 4 views
3

사내 웹 서비스를 사용하여 문자열 주소를 위도/경도 문자열로 변환하는 간단한 메서드 DLL을 만들었습니다. 코드는 간단히 다음과 같습니다.CLR SQL 함수 실행 문제

public class GeoCodeLib 
{ 
    [SqlFunction(IsDeterministic=false)] 
    public SqlString GetLatLon(SqlString addr) 
    { 
     Geo.GeoCode gc = new Geo.GeoCode(); 
     Geo.Location loc = gc.GetLocation(addr.Value); 
     return new SqlString(string.Format("{0:N6}, {1:N6}", loc.LatLon.Latitude, loc.LatLon.Longitude)); 
    } 
} 

.NET Framework 2.0을 대상으로했습니다. 우리는 SQL Server 2008 R2를 사용하고 있습니다. 어셈블리가 데이터베이스에 추가되었습니다 (어셈블리는 GeoCodeSqlLib.dll이라고 함). 이에 대한 사용 권한을 설정하지 않았습니다.

나는 그것을 부를 수 없다. 나는 시도했다 : 나는 시도했다 Cannot find either column "GeoCodeSqlLib" or the user-defined function or aggregate "GeoCodeSqlLib.GeoCodeLib.GetLatLon", or the name is ambiguous.

나에게 메시지를 제공

select GeoCodeSqlLib.GeoCodeLib.GetLatLon('12143 Thompson Dr. Fayetteville, AR 72704') 

: 나에게 메시지를 제공

CREATE FUNCTION GetLatLon(@amount varchar(max)) RETURNS varchar(max) 
AS EXTERNAL NAME GeoCodeSqlLib.GeoCodeLib.GetLatLon 

, Could not find Type 'GeoCodeLib' in assembly 'GeoCodeSqlLib'.

을 나는 분명 해요 무언가를 놓침. 설명서의 샘플은 모두 기본적으로 빠졌지 만 필자는 설명서에서 찾을 수 없었습니다. 모든 도움

업데이트

감사합니다. 몇 가지 :

  • 웹 서비스 호출을하려면 외부 액세스 권한이 있어야합니다. SQL Server 프로젝트를 만들 필요가 있다는 것을 알지 못했습니다. 난 그냥 정규 C# 클래스 라이브러리를하고 있었다.
  • 그래서 SQL Server 프로젝트를 만들었습니다. SQL Server 프로젝트는 웹 서비스 참조를 지원하지 않습니다. 원래 DLL에 대한 참조를 추가하려고 시도 했으므로 새 SQL Server 프로젝트 DLL이 원본 DLL (원래 질문의 코드)에 대한 프록시 역할을합니다.
  • 그러나 이것은 Assembly 'geocodesqllib, version ...' was not found in the SQL catalog.입니다. 그러나 외부 액세스가 필요하기 때문에 카탈로그에 추가 할 수 없습니다. SQL Server 이외 프로젝트에서 수행 할 수없는 액세스 (해당 ).

정말 이걸 쉽게하고 싶지 않습니까?

아래에있는 내 의견으로 당 2

업데이트, 마지막 문제는 설정 파일로 나타납니다. 설정을 찾지 못했습니다. 서버의 이름을 보호하기 위해 변경되었습니다 무고한 :

<applicationSettings> 
    <GeoCodeSqlLib.Properties.Settings> 
     <setting name="GeoCodeSqlLib_ourserver_GeoCode" serializeAs="String"> 
      <value>http://ourserver/GeoCode.svc</value> 
     </setting> 
    </GeoCodeSqlLib.Properties.Settings> 
</applicationSettings> 

내가 오류는 다음과 같습니다

System.Configuration.SettingsPropertyNotFoundException: The settings property 'GeoCodeSqlLib_ourserver_GeoCode' was not found. 
+1

방법은'static'해야합니다. –

+0

의견과 관련하여 귀하가 옳다. 나는 그 오류 메시지의 일부를 놓쳤다. 내 대답을 삭제합니다. 감사! – JuanR

답변

4

몇 가지 : 제론 Mostert가에서 언급 한 바와 같이

  1. 질문에 대한 의견을 말하면 SQLCLR 메서드는 static으로 선언되어야합니다.

  2. CREATE FUNCTION 문에는 VARCHAR 대신 NVARCHAR을 사용해야합니다.SQLCLR은 VARCHAR을 지원하지 않습니다.

  3. CREATE FUNCTION 문에서 입력 매개 변수 및 반환 유형으로 MAX을 사용할 필요가 없습니다. 위도와 경도 조합은 항상 4000 자 미만이어야하며 주소도 4000 자 미만이어야합니다. 서명에 하나의 MAX 데이터 유형이 있어도 성능이 크게 떨어집니다. 둘 다 NVARCHAR(4000)이되도록하는 것이 좋습니다.

  4. "형식을 찾을 수 없습니다."오류가 발생하는 경우 질문의 코드에 표시되지 않는 네임 스페이스가있을 가능성이 큽니다. EXTERNAL NAME 구문은이 정책에 대한

    CREATE FUNCTION dbo.GetLatLon(@Address NVARCHAR(4000)) 
    RETURNS NVARCHAR(4000) 
    AS EXTERNAL NAME GeoCodeSqlLib.[{namespace_name}.GeoCodeLib].GetLatLon; 
    
  5. :

    EXTERNAL NAME AssemblyName.[NamespaceName.ClassName].MethodName; 
    

    는 그래서 찾고 뭔가를 끝낼해야

    내가 .NET Framework 2.0을 대상으로했다. 우리는 SQL 서버를 사용하고 2008 R2

    당신은 3.0 및 CLR 2.0에서 3.5 실행 및 SQL 서버 2005, 2008 및 2008 R2를 같이 .NET Framework 버전 3.5를 사용할 수 있습니다은 CLR 2.0에 연결되어

    .

    비주얼 스튜디오 프로젝트에게 "데이터베이스 프로젝트"를 만들 필요가하지만 확인하지 않습니다 아니, 당신은 않습니다 질문에 UPDATE 섹션으로 당


조금 더 쉽게 출판 할 수 있습니다.

라이브러리를 EXTERNAL_ACCESS으로 설정하려면 Visual Studio에서 데이터베이스 프로젝트의 프로젝트 속성을 통해 설정할 수 있습니다. 또한 CREATE ASSEMBLY 문에 WITH PERMISSION_SET = EXTERNAL_ACCESS을 추가 할 수 있습니다.이 진술은 어쨌든 SSDT에서 처리하는 모든 Visual Studio 게시 프로세스입니다.

  1. 로그인 또한 비주얼 스튜디오 프로젝트에 쉽게 수행 할 수 있습니다 총회 (:

    이제 순서대로 다음을 수행 할 필요가 EXTERNAL_ACCESS 모든 조립을 설정할 수 (또는 UNSAFE에) 할 수 등록 정보)를 확인하고 "키 파일을 암호로 보호"해야합니다.

  2. DLL을 만들 수 있도록 프로젝트를 게시 (게시하지 않음)하십시오.

  3. master 데이터베이스에서 해당 DLL에서 비대칭 키를 만듭니다.

  4. 여전히 master 인 경우 해당 비대칭 키로 로그인하십시오.

  5. 새로운 키 기반 로그인에 EXTERNAL ACCESS ASSEMBLY 권한을 부여하십시오.

지금 당신은 오류가없는 (중 어떤 협의회 CREATE ASSEMBLY 또는 ALTER ASSEMBLY 문은 특정 키로 서명에) WITH PERMISSION_SET = EXTERNAL_ACCESS 사용할 수 있습니다.

SQLCLR을 처음으로 사용하는 방법을 명확하게 이해하는 데 도움이 될 수 있습니다. 심지어 사용하는 방법을 설명하는 일련의

Stairway to SQLCLR

레벨 7 : 나는 SQL Server 중앙에이 주제에 쓰고 기사의 시리즈를 참조하십시오 (무료 등록은 해당 사이트의 콘텐츠를 읽을 필요) Visual Studio/SSDT는 VS/SSDT가 보안 측면을 처리하지 않기 때문에 자동화 된 방식으로 작동하도록 위에서 언급 한 단계를 관리합니다 (이는 사람들이 데이터베이스를 설정하는 쉬운 경로로 이동하도록 유도하므로 슬프다) TRUSTWORTHY ON 보안 구멍입니다). 그리고 다음 기사에서는 Visual Studio 내에서 T-4 템플릿을 사용하는 더욱 쉬운 방법을 설명합니다. 이 답변에 업데이트 2 부분과 추가 의견에 대한


: 각 데이터베이스/소유자 조합 당 하나의 응용 프로그램 도메인, 특정 어셈블리 내 코드를 실행하는 모든 세션이 있으므로

  1. 정확한 코드와 메모리를 공유하게 될 것입니다. 정적 클래스 변수 (예 : 앱 도메인의 수명 동안 가치를 유지하는 변수)가 있으면 모든 세션에서 공유되며 예상치 못한/신뢰할 수없는 동작으로 이어질 수 있습니다. 이러한 이유로 정적 클래스 변수를 사용하려면 어셈블리를 UNSAFE으로 표시해야합니다. 그렇지 않으면 변수가 readonly으로 표시된 경우 SAFEEXTERNAL_ACCESS 어셈블리에 정적 클래스 변수를 포함 할 수 있습니다.

  2. 앱 구성 파일은 사용할 수 있지만이 경우 "app"는 SQL Server입니다. 따라서 특정 CLR 버전 (귀하의 경우에는 CLR 2.0)의 모든 프로세스에 대해 전역 인 machine.config에 항상 구성 정보를 배치하거나이 대답과 같이 SQL Server에 대한 구성 파일을 만들 수 있습니다 또한 여기에 SO에 광산 :

    Does SQL Server CLR Integration support configuration files?

+0

감사합니다. 나는 가까워지고 있지만 여전히 몇 가지 딸꾹질이 있습니다. – Pete

+1

@ Pete ** 업데이트 ** 섹션을 해결하기 위해 추가 정보가 업데이트되었습니다. –

+1

나는 거의 다 왔다고 생각하지만 내 DBA가 돌아와서 마지막 조금을 기다리고있다. 도와 주셔서 정말 감사합니다. 일단 대답이 나오면 받아 들일 것입니다. 나는 당신의 기사를 아직 상세히 읽지 않았지만 네임 스페이스 (나를 조금 넘어 뜨 렸음)가 당신의 시리즈에서 실제로 다루어지지 않는다는 것을 알았다. 나는 C#에서 네임 스페이스에없는 코드를 작성한 적이 없으며 위의 CREATE FUNCTION 예제에서 다루지 않았다면 알아 내지 못했을 것입니다. 나는 이것이 중요한 지적이라고 생각합니다! – Pete