Sqlserver
 sql >> डेटाबेस >  >> RDS >> Sqlserver

मैं एक बड़े बफर को बनाए बिना SQL सर्वर BLOB में .NET ऑब्जेक्ट का एक बड़ा ग्राफ कैसे क्रमबद्ध करूं?

बड़े डेटा के लिए इसे वास्तव में इनायत से संभालने के लिए कोई अंतर्निहित ADO.Net कार्यक्षमता नहीं है। समस्या दो गुना है:

  • एसक्यूएल कमांड (कमांडों) में 'लिखने' के लिए कोई एपीआई या स्ट्रीम के रूप में पैरामीटर नहीं है। किसी स्ट्रीम को स्वीकार करने वाले पैरामीटर प्रकार (जैसे FileStream ) स्ट्रीम को पढ़ें . के लिए स्वीकार करें इससे, जो लिखने . के क्रमांकन शब्दार्थ से सहमत नहीं है एक धारा में। कोई फर्क नहीं पड़ता कि आप इसे किस तरह से घुमाते हैं, आप पूरे सीरियल ऑब्जेक्ट की मेमोरी कॉपी में खराब हो जाते हैं।
  • भले ही उपरोक्त बिंदु हल हो जाए (और यह नहीं हो सकता), टीडीएस प्रोटोकॉल और SQL सर्वर जिस तरह से मापदंडों को स्वीकार करता है वह बड़े मापदंडों के साथ अच्छी तरह से काम नहीं करता है क्योंकि पूरे अनुरोध को निष्पादन में लॉन्च होने से पहले पहले प्राप्त किया जाना है। और यह SQL सर्वर के अंदर ऑब्जेक्ट की अतिरिक्त प्रतियां बनाएगा।

तो आपको वास्तव में इसे एक अलग कोण से देखना होगा। सौभाग्य से, एक काफी आसान समाधान है। ट्रिक अत्यधिक कुशल UPDATE .WRITE . का उपयोग करना है टी-एसक्यूएल कथनों की एक श्रृंखला में एक-एक करके डेटा के टुकड़ों में सिंटैक्स और पास करें। यह MSDN अनुशंसित तरीका है, ADO.NET में बड़े-मान (अधिकतम) डेटा को संशोधित करना देखें। यह जटिल लगता है, लेकिन वास्तव में ऐसा करना और स्ट्रीम क्लास में प्लग करना बहुत आसान है।

ब्लॉबस्ट्रीम वर्ग

यह घोल की रोटी और मक्खन है। एक स्ट्रीम व्युत्पन्न वर्ग जो टी-एसक्यूएल ब्लॉब राइट सिंटैक्स के लिए कॉल के रूप में लिखें विधि को लागू करता है। सीधे आगे, इसके बारे में दिलचस्प बात यह है कि इसे पहले अपडेट का ट्रैक रखना है क्योंकि UPDATE ... SET blob.WRITE(...) सिंटैक्स NULL फ़ील्ड पर विफल हो जाएगा:

class BlobStream: Stream
{
    private SqlCommand cmdAppendChunk;
    private SqlCommand cmdFirstChunk;
    private SqlConnection connection;
    private SqlTransaction transaction;

    private SqlParameter paramChunk;
    private SqlParameter paramLength;

    private long offset;

    public BlobStream(
        SqlConnection connection,
        SqlTransaction transaction,
        string schemaName,
        string tableName,
        string blobColumn,
        string keyColumn,
        object keyValue)
    {
        this.transaction = transaction;
        this.connection = connection;
        cmdFirstChunk = new SqlCommand(String.Format(@"
UPDATE [{0}].[{1}]
    SET [{2}] = @firstChunk
    WHERE [{3}] = @key"
            ,schemaName, tableName, blobColumn, keyColumn)
            , connection, transaction);
        cmdFirstChunk.Parameters.AddWithValue("@key", keyValue);
        cmdAppendChunk = new SqlCommand(String.Format(@"
UPDATE [{0}].[{1}]
    SET [{2}].WRITE(@chunk, NULL, NULL)
    WHERE [{3}] = @key"
            , schemaName, tableName, blobColumn, keyColumn)
            , connection, transaction);
        cmdAppendChunk.Parameters.AddWithValue("@key", keyValue);
        paramChunk = new SqlParameter("@chunk", SqlDbType.VarBinary, -1);
        cmdAppendChunk.Parameters.Add(paramChunk);
    }

    public override void Write(byte[] buffer, int index, int count)
    {
        byte[] bytesToWrite = buffer;
        if (index != 0 || count != buffer.Length)
        {
            bytesToWrite = new MemoryStream(buffer, index, count).ToArray();
        }
        if (offset == 0)
        {
            cmdFirstChunk.Parameters.AddWithValue("@firstChunk", bytesToWrite);
            cmdFirstChunk.ExecuteNonQuery();
            offset = count;
        }
        else
        {
            paramChunk.Value = bytesToWrite;
            cmdAppendChunk.ExecuteNonQuery();
            offset += count;
        }
    }

    // Rest of the abstract Stream implementation
 }

ब्लॉबस्ट्रीम का उपयोग करना

इस नव निर्मित ब्लॉब स्ट्रीम क्लास का उपयोग करने के लिए आप एक BufferedStream . में प्लग इन करें . कक्षा में एक छोटा सा डिज़ाइन होता है जो केवल तालिका के कॉलम में स्ट्रीम लिखने का काम करता है। मैं किसी अन्य उदाहरण से तालिका का पुन:उपयोग करूंगा:

CREATE TABLE [dbo].[Uploads](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [FileName] [varchar](256) NULL,
    [ContentType] [varchar](256) NULL,
    [FileData] [varbinary](max) NULL)

मैं क्रमबद्ध करने के लिए एक डमी ऑब्जेक्ट जोड़ूंगा:

[Serializable]
class HugeSerialized
{
    public byte[] theBigArray { get; set; }
}

अंत में, वास्तविक क्रमबद्धता। हम पहले Uploads . में एक नया रिकॉर्ड डालेंगे तालिका बनाएं, फिर एक BlobStream बनाएं नई सम्मिलित आईडी पर और सीधे इस स्ट्रीम में क्रमांकन को कॉल करें:

using (SqlConnection conn = new SqlConnection(Settings.Default.connString))
{
    conn.Open();
    using (SqlTransaction trn = conn.BeginTransaction())
    {
        SqlCommand cmdInsert = new SqlCommand(
@"INSERT INTO dbo.Uploads (FileName, ContentType)
VALUES (@fileName, @contentType);
SET @id = SCOPE_IDENTITY();", conn, trn);
        cmdInsert.Parameters.AddWithValue("@fileName", "Demo");
        cmdInsert.Parameters.AddWithValue("@contentType", "application/octet-stream");
        SqlParameter paramId = new SqlParameter("@id", SqlDbType.Int);
        paramId.Direction = ParameterDirection.Output;
        cmdInsert.Parameters.Add(paramId);
        cmdInsert.ExecuteNonQuery();

        BlobStream blob = new BlobStream(
            conn, trn, "dbo", "Uploads", "FileData", "Id", paramId.Value);
        BufferedStream bufferedBlob = new BufferedStream(blob, 8040);

        HugeSerialized big = new HugeSerialized { theBigArray = new byte[1024 * 1024] };
        BinaryFormatter bf = new BinaryFormatter();
        bf.Serialize(bufferedBlob, big);

        trn.Commit();
    }
}

यदि आप इस सरल नमूने के निष्पादन की निगरानी करते हैं तो आप देखेंगे कि कहीं भी एक बड़ी क्रमांकन धारा नहीं बनाई गई है। नमूना [1024*1024] की सरणी आवंटित करेगा लेकिन यह डेमो उद्देश्यों के लिए क्रमबद्ध करने के लिए कुछ है। यह कोड एक बार में 8040 बाइट्स के SQL सर्वर BLOB अनुशंसित अद्यतन आकार का उपयोग करते हुए, बफ़र्ड तरीके से, चंक द्वारा खंडित करता है।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL सर्वर IF बनाम IIF ():क्या अंतर है?

  2. SQL सर्वर क्वेरी में NULL को 0 से बदलना

  3. SQL सर्वर में SHOWPLAN_XML कैसे काम करता है

  4. पता करें कि क्या ऑब्जेक्ट OBJECTPROPERTY () के साथ SQL सर्वर में एक टेबल-वैल्यूड फंक्शन है

  5. Inno सेटअप का उपयोग करके MS SQL सर्वर से कैसे कनेक्ट करें?