CLRSQL 聚合函数。 LINQ 代码在 CLR 函数中工作,但无法在聚合中部署
感谢您阅读本文,
VS2010针对SQLServer2008企业版,开发CLR Aggregate函数来计算MODE,该函数返回此错误:
“第 1 行创建聚合失败 因为类型“CMode”不符合 由于现场而符合 UDAGG 规范 'CS$<>9__CachedAnonymousMethodDelegate1'。”
此处产生错误:
int mode = list.GroupBy(n => n).
OrderByDescending(g => g.Count()).
Select(g => g.Key).FirstOrDefault();
这是完整的代码:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
[Serializable]
[SqlUserDefinedAggregate(Format.UserDefined , MaxByteSize = 8000)]
public struct CMode : IBinarySerialize
{
private List<int> list;
public void Init()
{
this.list = new List<int>();
}
public void Accumulate(SqlInt16 Value)
{
this.list.Add(Value.Value);
}
public void Merge(CMode Group)
{
this.list.AddRange(Group.list.ToArray());
}
public SqlDecimal Terminate()
{
SqlInt16 rtn = new SqlInt16();
int mode = list.GroupBy(n => n).
OrderByDescending(g => g.Count()).
Select(g => g.Key).FirstOrDefault();
rtn = (SqlInt16)mode;
return rtn;
}
//IBinarySerialize
public void Read(BinaryReader r)
{
int itemCount = r.ReadInt16();
this.list = new List<int>(itemCount);
for (int i = 0; i <= itemCount - 1; i++)
{
this.list.Add(r.ReadInt16());
}
}
//IBinarySerialize
public void Write(BinaryWriter w)
{
w.Write(this.list.Count);
foreach (Int16 s in this.list)
{
w.Write(s);
}
}
}
任何指导将不胜感激!
我能够在 SQLCLR 函数中运行所需的代码,这将验证我是否拥有所有授权,dll 在那里,等等..:
u
sing System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Linq.Expressions;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Linq;
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlInt16 SQLCLR2008MODE()
{
List<int> list;
list = new List<int>();
list.Add(7);
list.Add(1);
list.Add(2);
list.Add(2);
list.Add(3);
list.Add(3);
list.Add(4);
list.Add(4);
list.Add(5);
list.Add(5);
list.Add(6);
int mode = list.GroupBy(n => n).
OrderByDescending(g => g.Count()).
Select(g => g.Key).FirstOrDefault();
return (Int16)mode;
}
};
期待您的评论。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
试试这个代码。您的代码不起作用,因为编译器将您的隐式 Func 委托重写为编译委托(我强烈建议使用反射器亲眼检查这一点)。这还不错,因为它主要是出于性能原因(以避免每次调用时进行编译),但不幸的是,这会创建一个不可序列化的字段,并且不能与 SQL Server 很好地配合。为了避免这种情况,您必须使用表达式并手动编译它们。我的实现仅在整个调用(init)中创建一次委托。
总而言之,我强烈建议使用 HashSet 集合和某种分组甚至 SortedHashSet 来实现模式。
Try this code. YOur code does not work, because compiler rewrites Your implicit Func delegates to compiled delegates (i strongly recommend using reflector to check this on your own eyes). That would not be bad since it is mainly for performance reasons (to avoid compilation every time this is called) but unfortunately this creates a field which is not serializable and just doe not work well with SQL Server. To avoid that, You have to use expressions and compile them manually. My implemenatation only creates the delegates once in whole call (the init).
All in all I would strongly recommend implementing mode using the HashSet collection with some kind of a grouping or perhaps even SortedHashSet.
为了计算众数,我决定用 SQL 进行编码。即使查询针对数百万行,它也能很快得到结果。该查询计算每天的众数。
那是:
In order to calculate the mode, I decided to code it in SQL. It has resulted quite quick even when the query goes against millions of rows. The query calculates the Mode for each day.
That is:
非常感谢幸运卢克!!!!
我在执行代码时遇到了一些错误,涉及空值。在这个过程的最后,我用 SQL 对其进行了编码,它的工作速度非常快。根据您的回答,我尝试实施 Mediam。它工作正常,但有 8000 个参数大小限制。任何有兴趣学习如何克服该限制的人都可以转到 Expert SQL 2005 的第 6 章并实现字典以避免序列化。
Many thanks Luckyluke !!!!
I got some errors while executing your code, something regarding nulls values. At the end of the process, I coded it with SQL and it does the job very fast. Following the idea of your answer, I have tried to implement the Mediam. It works fine but it has the 8000 parameter size limitation. Anyone interested in learning how to overpass that limitation can go to Chapter 6 of Expert SQL 2005 and implement a dictionary to avoid serialization.
我使用 .NET 3.5 在 Visual Studio 2010 中创建了两个 UDA 来计算 IRR 和 NPV。它们在 SQL 2012 上运行和部署得很好。但是,当我尝试将它们部署到 SQL 2008R2 时,它们失败了,并出现了可怕的“不符合 UDAGG 规范”错误。我尝试实施 LuckyLuke 的方法,但没有成功。只有在从 UDA 类中删除所有 lambda 表达式和 LINQ 后,我才最终在 SQL 2008R2 上取得成功。有趣的是,我仍然能够在我的 UDA 使用的类中使用这些语言元素。
I created two UDAs to compute IRR and NPV in Visual Studio 2010 using .NET 3.5. They ran and deployed nicely on SQL 2012. However, when I attempted to deploy them to SQL 2008R2, they failed with the dreaded 'does not conform to UDAGG specification' error. I tried to implement LuckyLuke's approach but had no success. I was finally successful on SQL 2008R2 only after I removed all lambda expressions and LINQ from the UDA classes. Interestingly, I was still able to use these language elements in a class used by my UDAs.