我已根据我的博客条目在.Net 3.5中创建了用户定义类型:
http://jwsadlerdesign.blogspot.com/2009/04/this-is-how-you-register.html
使用SQL与nHibernate等技术时,这种方法很有效。
但是,当我尝试将我的LinQ映射到SQL类以使用此UDT(属性定义而不是XML)时,我将该属性设置为枚举。我无法让LinQ映射到这种类型。我尝试过Image,Binary,varchar和integer,所有这些似乎都会发出Invalid Cast错误。
特别是我得到错误'无法将类型'ISTD.InstallManager.Common.Classes.SQLUDTTargetType'的对象强制转换为'System.Byte []',任何想法或帮助将不胜感激。
詹姆斯。
答案 0 :(得分:2)
更新:我最近自己遇到了这个问题,发现之前的解决方案还不完整。尽管所有文档都说过,但 可能会这样做,但有些痛苦。
为了您自己的方便,第一步是实现一些转换运算符:
public class MyUDT : INullable, IBinarySerialize
{
// Class implementation would go here
// ...
public static explicit operator MyUDT(byte[] data)
{
using (MemoryStream stream = new MemoryStream(data))
{
using (BinaryReader reader = new BinaryReader(stream))
{
MyUDT result = new MyUDT();
result.Read(reader);
return result;
}
}
}
public static explicit operator byte[](MyUDT x)
{
using (MemoryStream ms = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(ms))
{
x.Write(writer);
}
return ms.ToArray();
}
}
}
无论你如何声明属性,Linq to SQL仍然会拒绝给你UDT字段。所以你必须给它一个二进制字段。您不需要存储过程或任何自定义SQL,只需向表中添加计算列:
ALTER TABLE MyTable
ADD UDTField_Data AS CAST(UDTField AS varbinary(len))
其中 len 是您在 MaxByteSize 属性中定义的UDT。
现在您终于可以访问列数据了。您可能想要使用UDT作为新属性的返回类型,认为Linq to SQL将找到您的转换运算符并自动从字节数组转换;不要打扰。 Linq to SQL将决定它实际上是一个序列化的.NET对象,并发出一条消息,说明“输入流不是有效的二进制格式”。相反,您需要另一层间接:
private MyUDT udtField;
[Column(Name = "UDTField_Data", DbType = "varbinary(len)")]
private byte[] UdtFieldData
{
get { return (byte[])udtField; }
set { udtField = (MyUDT)value; }
}
public MyUDT UdtProperty
{
get { return udtField; }
set { udtField = value; }
}
一些注意事项,以明确这里发生了什么:
不幸的是,你必须跳过这么多箍才能让它发挥作用,但它确实有效。通过Linq表面设计师进行这种按摩可能会有困难,这只是我不使用它的几个原因之一;最好自己编写类,并在必要时使用SqlMetal帮助您。