rsj*_*ffe 3 sql-server c# sql-clr sql-server-2014
使用以下代码,我使用 csc 来编译 dll。然后我将程序集添加到 sql server 2014 使用
CREATE ASSEMBLY ReplaceMultiWord from 'd:\bcp\ReplaceMultiWord.dll' WITH PERMISSION_SET = SAFE;
Run Code Online (Sandbox Code Playgroud)
然后成功添加了第一个功能
CREATE FUNCTION dbo.ReplaceMultiWord
(@inputString AS NVARCHAR(MAX), @replacementSpec AS XML) RETURNS NVARCHAR(MAX)
AS
EXTERNAL NAME ReplaceMultiWord.UserDefinedFunctions.ReplaceMultiWord;
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试添加第二个功能时
CREATE FUNCTION dbo.CanReplaceMultiWord
(@inputString AS NVARCHAR(MAX), @replacementSpec AS XML) RETURNS BIT
AS
EXTERNAL NAME ReplaceMultiWord.UserDefinedFunctions.CanReplaceMultiWord;
Run Code Online (Sandbox Code Playgroud)
我收到错误
Could not find method 'CanReplaceMultiWord' for type 'UserDefinedFunctions' in assembly 'ReplaceMultiWord'
Run Code Online (Sandbox Code Playgroud)
下面是我的代码。为什么 sql server 看不到第二个函数?
using System;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Xml;
public partial class UserDefinedFunctions
{
//TODO: Concurrency?
private static readonly Dictionary<string, ReplaceSpecification> cachedSpecs =
new Dictionary<string, ReplaceSpecification>();
[SqlFunction(IsDeterministic = true,
IsPrecise = true,
DataAccess = DataAccessKind.None,
SystemDataAccess = SystemDataAccessKind.None)]
public static SqlString ReplaceMultiWord(SqlString inputString, SqlXml replacementSpec)
{
//TODO: Implement something to drop things from the cache and use a shorter key.
string s = replacementSpec.Value;
ReplaceSpecification rs;
if (!cachedSpecs.TryGetValue(s, out rs))
{
var doc = new XmlDocument();
doc.LoadXml(s);
rs = new ReplaceSpecification(doc);
cachedSpecs[s] = rs;
}
string result = rs.GetResult(inputString.ToString());
return new SqlString(result);
}
[SqlFunction(IsDeterministic = true,
IsPrecise = true,
DataAccess = DataAccessKind.None,
SystemDataAccess = SystemDataAccessKind.None)]
public static SqlBoolean CanReplaceMultiWord(SqlString inputString, SqlXml replacementSpec)
{
string s = replacementSpec.Value;
ReplaceSpecification rs;
if (!cachedSpecs.TryGetValue(s, out rs))
{
var doc = new XmlDocument();
doc.LoadXml(s);
rs = new ReplaceSpecification(doc);
cachedSpecs[s] = rs;
}
return rs.IsMatch(inputString.ToString());
}
internal class ReplaceSpecification
{
internal ReplaceSpecification(XmlDocument doc)
{
Replacements = new Dictionary<string, string>();
XmlElement root = doc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("x");
string pattern = null;
foreach (XmlNode node in nodes)
{
if (pattern != null)
pattern = pattern + "|";
string find = node.Attributes["find"].Value.ToLowerInvariant();
string replace = node.Attributes["replace"].Value;
pattern = pattern + Regex.Escape(find);
Replacements[find] = replace;
}
if (pattern != null)
{
pattern = "(?:" + pattern + ")";
Regex = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
}
}
private Regex Regex { get; set; }
private Dictionary<string, string> Replacements { get; set; }
internal string GetResult(string inputString)
{
if (Regex == null)
return inputString;
return Regex.Replace(inputString,
(Match m) =>
{
string s;
if (Replacements.TryGetValue(m.Value.ToLowerInvariant(), out s))
{
return s;
}
else
{
throw new Exception("Missing replacement definition for " + m.Value);
}
});
}
internal bool IsMatch(string inputString)
{
if (Regex == null)
return false;
return Regex.IsMatch(inputString);
}
}
}
Run Code Online (Sandbox Code Playgroud)
您的代码没有任何问题,至少不是问题中发布的代码。我将它复制并粘贴到 Visual Studio 2015 中,并且编译和部署没有错误。我想也许你可能有一个重载的方法,CanReplaceMultiWord
因为这些方法是不允许的,但我通过创建一个几乎相同签名的空方法来测试该场景,只是更改SqlString
为SqlChars
. 它也编译和部署得很好,但这次没有创建dbo.CanReplaceMultiWord
. 我尝试通过您的CREATE FUNCTION
语句手动创建,但出现错误,提示存在“不止一种方法”CanReplaceMultiWord
且无法重载;我没有得到任何关于“找不到方法”的信息。
所以,我想也许你可能会以某种方式在CREATE FUNCTION
语句的方法名称中有一个不可打印的字符(可能是控制字符?)。尝试删除该EXTERNAL NAME AS
行并重新键入。虽然,我确实从“编辑”页面复制并粘贴了您的代码,因此如果您复制并粘贴到问题中,那么它通常也会被复制到那里(除非他们没有或可能在进入系统的途中被清除, 没有把握)。尽管如此,我仍然发现CREATE FUNCTION
语句中的方法名称很可能有问题(不知何故,因为它适用于我的系统),因为如果您的程序集名称错误,您会得到:
在数据库“your_db_name”的 SQL 目录中找不到程序集“xxxxxxxxxx”。
正确的程序集名称但错误的类名返回:
在程序集“xxxxxxxxxx”中找不到类型“yyyyyyyyyyy”。
另外,我强烈建议使用 Visual Studio 进行编译。“社区版”是免费的,所以没有(好的)理由不使用它。有几个选项(实际上很多)可以传递给它处理得很好的 csc.exe。即使您不将它用于最终部署(我没有),它也非常适合开发和测试。
PS 使用 VS 的一个好处是它通过将 DLL 字节转换为十六进制字符串进行部署,以便它可以执行CREATE ASSEMBLY FROM 0x4D....
,这不仅更便于移植,而且您不可能拥有错误版本的程序集(假设您正在使用最近的部署/创建脚本)。
边注:
将RegexOptions.Compiled
选项与基于对象的 RegEx 一起使用时要小心,因为一旦方法超出范围,编译的定义就会被丢弃。我可能读错了您的代码,但看起来 RegEx 实际上只执行一次,这对于使用RegexOptions.Compiled
. 您要么想摆脱RegexOptions.Compiled
或切换到静态方法(当然,除非我误读了代码;-)。有关更多详细信息,请参阅正则表达式选项的 MSDN 页面。
归档时间: |
|
查看次数: |
934 次 |
最近记录: |