2010-11-22 14 views
1

SQL 2005には、以下のエラーを生成し続けるUDAがあります。私はこれが8000の最大バイトサイズの制限に起因する可能性が高いと推測しています....私はこれを回避するために使用することができます回避策はありますか? 2005年にこの制限を回避するための提案はありますか?私は2008年はこれらの制限をオフにしていたと知っていますが、当面はアップグレードできません。 SQL 2005の場合UDAの生成エラー、不十分なバッファサイズ

A .NET Framework error occurred during execution of user-defined routine or aggregate "CommaListConcatenate": 
System.Data.SqlTypes.SqlTypeException: The buffer is insufficient. Read or write operation failed. 
System.Data.SqlTypes.SqlTypeException: 
    at System.Data.SqlTypes.SqlBytes.Write(Int64 offset, Byte[] buffer, Int32 offsetInBuffer, Int32 count) 
    at System.Data.SqlTypes.StreamOnSqlBytes.Write(Byte[] buffer, Int32 offset, Int32 count) 
    at System.IO.BinaryWriter.Write(String value) 
    at TASQLCLR.CommaListConcatenate.Write(BinaryWriter w) 

答えて

5

あなたは区切り文字を使用して、複数のパラメータの中に一つのパラメータを回して、8000バイトの制限を解決することができます。私は詳細を自分で調べる必要はありませんでしたが、ここで答えを見つけることができます:​​

SQL 2008の場合、-1にMaxByteSizeを渡す必要があります。 8000を超える数値を渡すと、SQLは8000バイトの制限があると不平を言って集約を作成させません。 -1を渡すと、この問題を回避することができ、集計を作成することができます(これも8000バイトを超えてテスト済みです)。

エラーは次のとおりです。

サイズ(100000) "Class.Concatenate" のためには、 有効範囲にありません。サイズでなければなりません-1またはここでは1と8000

間 数は、SQLで> 8000バイト、2008年

<Serializable(), SqlUserDefinedAggregate(Format.UserDefined, 
IsInvariantToNulls:=True, 
IsInvariantToDuplicates:=False, 
IsInvariantToOrder:=False, MaxByteSize:=-1)> 
<System.Runtime.InteropServices.ComVisible(False)> _ 
Public Class Concatenate Implements IBinarySerialize 
End Class 
+0

なぜこれが答えですか?リンクされている記事では、8kの制限を回避する方法が指定されていません。これは、連結機能が2つのパラメータを取るための回避策を示していますか? – CuppM

3

ショー以下のコードをサポートするために、VB.NETのための労働者階級の定義でありますSQLAggregate内の10進数のセットのメディアを計算する方法。これは、データ・ディクショナリを実装するサイズ・パラメータ制限の問題を解決します。アイデアは、あなたも専門家2005が行うように辞書を実装する必要が専門家のSQL Expressの2005

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.Linq.Expressions; 
using SafeDictionary; 


[Microsoft.SqlServer.Server.SqlUserDefinedAggregate(
Format.UserDefined, MaxByteSize=16)] 

public struct CMedian2 : IBinarySerialize 
{ 
    readonly static SafeDictionary<Guid , List<String>> theLists = new SafeDictionary<Guid , List<String>>(); 

    private List<String> theStrings; 
    //Make sure to use SqlChars if you use 
    //VS deployment! 
    public SqlString Terminate() 
    { 

     List<Decimal> ld = new List<Decimal>(); 
     foreach(String s in theStrings){ 
      ld.Add(Convert.ToDecimal(s)); 
     } 

     Decimal median; 
     Decimal tmp; 
     int halfIndex; 
     int numberCount; 


     ld.Sort(); 
     Decimal[] allvalues = ld.ToArray(); 

     numberCount = allvalues.Count(); 

     if ((numberCount % 2) == 0) 
      { 
       halfIndex = (numberCount)/2; 
       tmp = Decimal.Add(allvalues[halfIndex-1], allvalues[halfIndex]); 
       median = Decimal.Divide(tmp,2); 
      } 
     else 
      { 
       halfIndex = (numberCount + 1)/2; 
       median = allvalues[halfIndex - 1]; 
       tmp = 1; 
      } 

     return new SqlString(Convert.ToString(median)); 
    } 

    public void Init() 
     { 
     theStrings = new List<String>(); 
     } 

    public void Accumulate(SqlString Value) 
     { 
     if (!(Value.IsNull)) 
      theStrings.Add(Value.Value); 
     } 

    public void Merge(CMedian2 Group) 
     { 
     foreach (String theString in Group.theStrings) 
      this.theStrings.Add(theString); 
     } 

    public void Write(System.IO.BinaryWriter w) 
    { 
    Guid g = Guid.NewGuid(); 
     try 
     { 
      //Add the local collection to the static dictionary 
      theLists.Add(g, this.theStrings); 
      //Persist the GUID 
      w.Write(g.ToByteArray()); 
     } 
     catch 
     { 
      //Try to clean up in case of exception 
      if (theLists.ContainsKey(g)) 
      theLists.Remove(g); 
     } 
    } 
    public void Read(System.IO.BinaryReader r) 
    { 
     //Get the GUID from the stream 
     Guid g = new Guid(r.ReadBytes(16)); 
     try 
     { 
      //Grab the collection of strings 
      this.theStrings = theLists[g]; 
     } 
     finally 
     { 
      //Clean up 
      theLists.Remove(g); 
     } 
    } 
} 

から取られる:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 

namespace SafeDictionary 
{ 
public class SafeDictionary<K, V> 
{ 
    private readonly Dictionary<K, V> dict = new Dictionary<K,V>(); 
    private readonly ReaderWriterLock theLock = new ReaderWriterLock(); 

    public void Add(K key, V value) 
    { 
     theLock.AcquireWriterLock(2000); 
     try 
      { 
       dict.Add(key, value); 
      } 
     finally 
      { 
       theLock.ReleaseLock(); 
      } 
    } 

    public V this[K key] 
    { 
     get 
      { 
       theLock.AcquireReaderLock(2000); 
       try 
        { 
         return (this.dict[key]); 
        } 
       finally 
        { 
         theLock.ReleaseLock(); 
        } 
      } 
     set 
      { 
       theLock.AcquireWriterLock(2000); 
       try 
        { 
         dict[key] = value; 
        } 
       finally 
        { 
         theLock.ReleaseLock(); 
        } 
      } 
    } 

    public bool Remove(K key) 
    { 
     theLock.AcquireWriterLock(2000); 
     try 
      { 
       return (dict.Remove(key)); 
      } 
     finally 
      { 
       theLock.ReleaseLock(); 
      } 
    } 

    public bool ContainsKey(K key) 
    { 
     theLock.AcquireReaderLock(2000); 
     try 
      { 
       return (dict.ContainsKey(key)); 
      } 
     finally 
      { 
       theLock.ReleaseLock(); 
      } 
    } 
} 
} 

辞書は、安全でないコードの付与と別のアセンブリに展開する必要があります。考え方は、メモリデータ構造辞書を保持することによってすべての数値を直列化することを回避することです。

第6章■SQLCLR:アーキテクチャおよび 設計上の考慮事項。

ところで、この解決法は私にとっては役に立たなかった。とにかく、私はそれを試して楽しんでいます。他の用途では、それは良いパターンです。

関連する問題