2012-05-07 25 views
9

का उपयोग कर SQL INSERT के माध्यम से उप निर्देशिका बनाना पहले, I requested how to create a directory within a FileTable without using File I/O APIs। अब मैं मूल निर्देशिका में एक उपनिर्देशिका बनाना चाहता हूं जिसे मैंने अभी बनाया है। डालने के दौरान मेरे माता-पिता को कैसे असाइन करें? ऐसा लगता है कि parent_path_locator एक गणना कॉलम है।फ़ाइलटेबल

यह मेरी माता पिता बनाता है ...

INSERT INTO FileTable0 (name,is_directory,is_archive) VALUES ('Directory', 1, 0); 

मैं अपने FileTable में यह माता पिता के लिए एक बच्चे निर्देशिका कैसे बनाऊं?

उत्तर

9

के बाद से मैं एक उपनिर्देशिका बनाने के लिए उपयोग कर रहा हूं, यह मेरे लिए एक नया path_locator मूल्य उत्पन्न नहीं करेगा - यह केवल मौजूदा hierarchyids की व्याख्या करेगा।

DECLARE @parentdir table(path hierarchyid not null); 
DECLARE @subdir_locator hierarchyid 

-- Create Parent Directory, OUTPUT inserted parent path 
INSERT INTO FileTable0 (name,is_directory,is_archive) 
OUTPUT INSERTED.path_locator into @parentdir 
SELECT 'Directory', 1, 0 

-- Create new path_locator based upon parent 
SELECT @subdir_locator = dbo.GetNewPathLocator(path) from @parentdir 

-- Create Subdirectory 
INSERT INTO FileTable0 (name,path_locator,is_directory,is_archive) 
VALUES ('subdirectory', @subdir_locator, 1, 0); 

ऊपर कोड ब्लॉक default path_locator value discovered here कि एक GUID (उपयोग newid() विधि, और सरल पार्स) से एक नया hierarchyid प्रतिनिधित्व बनाता इस्तेमाल करता है। फ़ंक्शन GetNewPathLocator() SQL सर्वर में कहीं भी मौजूद नहीं है जो मुझे मिल सकता है (hierarchyid.GetDescendant() निकटतम मुझे मिल सकता है, लेकिन यह मूल संरचना का उपयोग नहीं करता है कि फ़ाइलटेबल पर निर्भर करता है)। SQL.NEXT में हो सकता है कि ...

CREATE FUNCTION dbo.GetNewPathLocator (@parent hierarchyid = null) RETURNS varchar(max) AS 
BEGIN  
    DECLARE @result varchar(max), @newid uniqueidentifier -- declare new path locator, newid placeholder  
    SELECT @newid = new_id FROM dbo.getNewID; -- retrieve new GUID  
    SELECT @result = ISNULL(@parent.ToString(), '/') + -- append parent if present, otherwise assume root 
        convert(varchar(20), convert(bigint, substring(convert(binary(16), @newid), 1, 6))) + '.' + 
        convert(varchar(20), convert(bigint, substring(convert(binary(16), @newid), 7, 6))) + '.' + 
        convert(varchar(20), convert(bigint, substring(convert(binary(16), @newid), 13, 4))) + '/'  
    RETURN @result -- return new path locator  
END 
GO 

समारोह GetNewPathLocator() भी trick from this SO post का उपयोग कर एक newid() अनुरोध के लिए एक एसक्यूएल दृश्य getNewID की आवश्यकता है।

create view dbo.getNewID as select newid() as new_id 

GetNewPathLocator() कॉल करने के लिए, आप डिफ़ॉल्ट पैरामीटर जो एक नई hierarchyid उत्पन्न या एक बच्चे hierarchyid नीचे के रूप में देखा बनाने के लिए एक मौजूदा hiearchyid स्ट्रिंग प्रतिनिधित्व (.ToString()) में पारित करेंगे ... उपयोग कर सकते हैं

SELECT dbo.GetNewPathLocator(DEFAULT); -- returns /260114589149012.132219338860058.565765146/ 
SELECT dbo.GetNewPathLocator('/260114589149012.132219338860058.565765146/'); -- returns /260114589149012.132219338860058.565765146/141008901849245.92649220230059.752793580/ 
0

बजाय कोड में hierarchyid पुन: बनाने की कोशिश करते हैं मैं path_locator अद्यतन करने का विकल्प चुना के बाद एसक्यूएल बनाया यह खुद आईडी है:

DECLARE @pathID hierarchyid; 
DECLARE @parentdir table(path hierarchyid not null); 

IF NOT EXISTS(SELECT 1 FROM FileAsset WHERE is_directory = 1 AND file_stream.GetFileNamespacePath() = '\Assets\Test') 
INSERT INTO FileAsset (name, is_directory) VALUES('Test', 1) 

SELECT @pathID = FileAsset.path_locator FROM FileAsset WHERE file_stream.GetFileNamespacePath() = '\Assets\Test' 

INSERT INTO FileAsset (name, file_stream) OUTPUT INSERTED.path_locator into @parentdir VALUES('MyDoc.txt', 0x) 

UPDATE FileAsset SET path_locator = '/' + REPLACE(@pathID.ToString(), '/','') + path_locator.ToString() WHERE path_locator = (SELECT [path] FROM @parentdir) 

जहां 'संपत्ति' मेरी फ़ाइलटेबल निर्देशिका का नाम है, 'टेस्ट' निर्देशिका का नाम है जिसे मैं अपनी फाइल में रखना चाहता हूं, 'MyDoc.txt' फ़ाइल नाम है और 0x फ़ाइलस्ट्रीम के लिए शून्य प्रविष्टि है।

मुझे यकीन है कि मैं इसे एक फ़ंक्शन में बदलना चाहता हूं, काफी आसान है।

देखें ...

CREATE PROCEDURE InsertFileAsset 

    @fileName varchar(255), 
    @dirName varchar(255), 
    @data varbinary(MAX), 
    @stream_id uniqueidentifier OUTPUT 
AS 
BEGIN 
    DECLARE @pathID hierarchyid; 
    DECLARE @parentdir table(path hierarchyid not null); 
    DECLARE @streamID table(streamID uniqueidentifier not null); 

    IF NOT EXISTS(SELECT 1 FROM FileAsset WHERE is_directory = 1 AND file_stream.GetFileNamespacePath() = '\Assets\' + @dirName) 
    INSERT INTO FileAsset (name, is_directory) VALUES(@dirName, 1) 

    SELECT @pathID = FileAsset.path_locator FROM FileAsset WHERE file_stream.GetFileNamespacePath() = '\Assets\' + @dirName 

    INSERT INTO FileAsset (name, file_stream) OUTPUT INSERTED.path_locator into @parentdir VALUES(@fileName, @data) 

    UPDATE FileAsset SET path_locator = '/' + REPLACE(@pathID.ToString(), '/','') + path_locator.ToString() OUTPUT inserted.stream_id INTO @streamID WHERE path_locator = (SELECT [path] FROM @parentdir) 

    SELECT @stream_id = streamID FROM @streamID 

    RETURN 
END 
GO 
+0

कुछ कठोर परीक्षण के बाद, ऐसा लगता है कि जब इस समानांतर में कहा जाता है अद्यतन बयान गतिरोध की संभावना है। – Tod

0

एक अन्य विकल्प CLR एकीकरण का उपयोग करें और कार्य करता है और सी # कोड के रूप में संग्रहित प्रक्रियाओं बनाने के लिए है।

मैंने अभी इसके लिए एक गिटहब सीएलआर एकीकरण परियोजना बनाई है। https://github.com/rhyous/Db.FileTableFramework

इसमें कई फ़ंक्शन या प्रक्रियाएं हैं जिन्हें आप चाहते हैं: CreateFile, CreateDirectory, DirectoryExists। और गिटहब पर निश्चित रूप से इसे किसी भी द्वारा संशोधित और सुधार किया जा सकता है।

0

मैं जवाब देने के लिए कुछ सुधार किए गए:

  1. समारोह रिटर्न स्ट्रिंग के बजाय hierarchyid
  2. अगर वहाँ एक माता पिता है, hierarchyid :: GetReparentedValue समारोह स्ट्रिंग के बजाय एक नया आईडी उत्पन्न करने के लिए प्रयोग किया जाता है संयोजन।

    create function doc.GetNewPathLocator (@parent hierarchyid = null) returns hierarchyid 
    as 
    begin 
        declare @id uniqueidentifier = (select new_id from dbo.GetNewID); 
        declare @path hierarchyid = (convert(hierarchyid, '/' + 
          convert(varchar(20), convert(bigint, substring(convert(binary(16), @id), 1, 6))) + '.' +  
          convert(varchar(20), convert(bigint, substring(convert(binary(16), @id), 7, 6))) + '.' +  
          convert(varchar(20), convert(bigint, substring(convert(binary(16), @id), 13, 4))) + '/')); 
        return case when @parent is null then @path else @path.GetReparentedValue(hierarchyid::GetRoot(), @parent) end; 
    end 
    go