O - - - - - - sqlclub
Vannak valójában itt két és fél darab. Első (InitMethod + FillRow + fnRecursive) - a TVF (. Táblázat - értékű függvény olyan függvény, amely visszaadja az eredményt táblázatos formában), fogadó bemenet a teljes elérési utat a mappát, és ebben az esetben a visszaállító rekordset szerkezete a következő:
ID HierarchyID, FullName nvarchar (1000), DateModified datetime2, DateCreated datetime2, LastAccessed datetime2, mérete bigint, isDir kicsit, Tulajdonságok XML
Az első mező szolgál azonosítóként a táblázatban bejegyzést. Ugyanakkor ez határozza meg a helyzetét a csomópont a hierarchiában, amely lehetővé teszi az építkezés fa asztal mellőzését hagyományos vezetékek szülő - gyermek. Cm. Ebben a témakörben üzenetét HierarchyID és a szülő-gyermek. Dir () és HierarchyID.
A következő mezők - a hagyományos fájl attribútumok: a teljes nevét (elérési út), az utolsó módosítás dátuma, a létrehozás dátuma, utolsó hozzáférés dátumát és mérete (bájt) és egy logikai jelzése, hogy az objektum egy fájlt vagy mappát.
CLR sósav TVF szétszerelt berendezés éhomi táblázatos CLR-funkciók TChaynikov. Belőle meg lehet tanulni, mit akar a horgony módszer InitMethod, iteratív FillRow, valamint a szerkezeti típus row_item és egy lista elemeinek ilyen típusú. Abban az esetben, mély navigációs mappa, almappák podfoldery kell turkálni körül, így azok rekurzívan az eljárás ugyanaz, mint a szülő mappa nevét. Alapvetően a rekurzív TVF nem ideológiailag eltér a szokásos, de csak abban az esetben, akkor olvasd el a hozzászólásokat a CLR TVF rekurzív és rekurzív TVF-2. Mint egy kiegészítő funkciója a rekurzió végez fnRecursive.
Amint a fájlok mozgatása, szeretnénk megjeleníteni semmilyen információt a haladás, a folyamatot. TVF nem képesek az semmit állapotát, de az ebből fakadó rekordseta, ezért úgy döntöttem, hogy hozzon létre egy magazin, mint, ahol írni a fájlt, és az aktuális időt. Logikus lenne, hogy tartsa együtt a többi SQL Server log üzeneteket. GetSqlErrLogPath () függvény megkapja azt a mappát, amelyben az SQL Server Error megtartja Logi. Hely szolgáltatás SQL Server objektumok szétszerelt a poszt Hogyan hitelt alapértelmezett helye az adatbázis fájlokhoz. Mivel ez a funkció az olyan redzhistri az eljárás InitMethod, amelyből ez az úgynevezett, kerül SystemDataAccessKind.Read attribútumot.
Rekurzív eljárás fnRecursive row_item létrehoz egy új típusú bejegyzést a listában minden fájlt vagy veszekedés podfoldera, töltő maga területén. HierarchyID nyert a szülő értékek és a legközelebbi szomszéd maradt. A kiterjesztett attribútumokat fog működni FileExtProps, mint az XML. amely szintén helyezünk a row_item. További attribútumok venni a tárgy IO.FileSystemInfo, ami egy általánosítása fájl és könyvtár. Ha a fájl mérete is hozott neki, ha a könyvtár, fnRecursive eljárást nevezi magát paraméterként a könyvtár.
Az összeállítás készül formájában osztály könyvtárak és deploitsya az SQL Server kézi mert használ a könyvtár SOMovskaya% Windir% \ System32 \ Shell32.dll. Elolvashatja róla a bejegyzést használja COMovskih dll SQL CLR. Emiatt az egységnek, el kell deploitsya hogyan biztonságos - lásd aláírása vagy külső biztonságos szerelés .. A fúvóka mi rögzítse derevyannenkoe, mert eddig a pontig még mindig nincs kivitelben olvasás. A legfrissebb jelentések Rosstat eltávolítása mssqlsystemresource .mdf lehetővé teszi az SQL Server, hogy a termelékenység 12,3% -kal. Deploymenta a lefordított összeszerelést végrehajtják segítségével T-SQL:
--select * from sys.objects
állapítsa @fullName nvarchar (500), @cmd nvarchar (1000), @i int = 0
állapítsa cur kurzort forward_only scroll_locks Select fullName a t ahol isDir = 0 frissítési tartalom; nyitott cur
1 = 1, míg kezdődik
lekérni a következő származó korcs be @fullName
ha @@ fetch_status <> 0 szünet
print öntött (@i a varchar (10)) +”. „+ @fullName
set @cmd = 'frissítés t beállított tartalom = (válassza BulkColumn a OPENROWSET (ömlesztett' '' + @fullName + '' 'single_blob) az f), ahol áram cur'
kezdődik próbát; exec (@cmd); end try
kezdődik fogás; print „Nem tudom letölteni a fájlt, mert a” + ERROR_MESSAGE (); end fogás
közel korcs; visszavételi cur
állítsa le nocount
Azt állítjuk elő egy másik fajta injekció formájában LoadDirWithFileContent eljárás. Ez eltér a funkciója, hogy a hajók InitMethod egy mappát közvetlenül a tábla, amelynek neve vezetjük rá, mint az egyik paraméter, ezért festékfoltok, mi aploudim az SQL Server, ha jelen vannak, és lehet önteni azonnal félelem nélkül túlfolyó memóriát. Táblázat, amely betölti a hipotézist kötelezővé kellene tenni sor mezők megadott nevét és típusát (lásd. 5. táblázat Dir a script). Rajtuk kívül lehetnek más területen a táblázatban. Kitöltésekor foltok belsejében CLRnoy eljárás használ egy határozat úgy utáni Import / Export blobovskih mezőket a fájlok - CLR. Ha valaki hallott SqlFileStream API, nem tudom, miért nem használja ezt a megközelítést, olvassa el a post részleges frissítést FILESTREAM. A szolgáltatás eljárás spRecursive ugyanazt a szerepet játssza, mint fnRecursive a TVF Dir () LoadDir a tárolt eljárást. Dir () függvény és az eljárás LoadDir lehet használni önállóan, és az az ötlete támadt, hogy kiadja azokat a formájában néhány módszerek az UDT, amely egyszerűen tekinthető egy tartályt az függvényeket. Sajnos, a TVF nem engedélyezett, mint egy UDT módszerek, így minden fog elhelyezkedni ömlesztve. Létrehozása LoadDir eljárások az összeállítás elindítása a következők:
drop funkció Dir
hozzon létre proc LoadDir @folder nvarchar (255), @shallowTraversal bit. @tblName sysName külső neve MyAssembly. FileSystem. LoadDirWithFileContent
ha object_id ( 'dir'. 'U') nem nulla csepp táblázatban Dir
create table Dir (ID HierarchyID. FullName nvarchar (1000), DateModified datetime2. DateCreated datetime2. LastAccessed datetime2. Tulajdonságok XML. mérete bigint. isDir bites. Tartalom varbinary (max))
exec LoadDir 'c: \ Temp'. 0. 'dir' --0, ha a merülés podfoldery; 1, ha a float finomra
Ez pontosan ugyanaz a rakodás: \ Temp 450 MB egy másik asztalhoz. Működő tartott 4 perc. 30 sec. ami a szokásostól eltérő. Amíg én kijavítottuk, tipikus alkalommal volt 3 percig. +/- pár másodpercig. Úgy tűnik, hogy az a tény, hogy én nem csepp asztal t. Általában t törölni táblázatok az eredményeket a funkciót, mielőtt a beavatkozáshoz, és most fordult zadvoeny alapjának mérete - nem 450 méter és 936 Ő lett avtopriraschat mdfnik, és ahogy ott feküdt a c: \ temp, elkezdtek befolyásolhatják a leolvasott egymást.
A napló jön létre a letöltés során. Ez fekszik ugyanabban a mappában, mint a ErrorLog, az úgynevezett kemény SqlFSLoader.log. Ahogy Flush () után történik minden egyes késztermék vonalak, akkor nyissa meg újra, és nézni a haladás a letöltési folyamatot.
SqlCommand cmd = cnn.CreateCommand ();
cmd.CommandText = "betét" + TableName + „(ID, FullName, DateModified, DateCreated, LastAccessed, Properties, méret, isDir, tartalom) értékek (@hid, @fullName, @dateModified, @dateCreated, @lastAccessed, @properties, @size, @isDir, @content) „;
cmd.Parameters.Add (új SqlParameter ( "@hid" SqlHierarchyId .Null).); //SqlDbType.SqlHierarchyId nem szerepel, meg kell csinálni értéket.
cmd.Parameters [ "@hid"] .UdtTypeName = "HierarchyID"; Egyébként // System.ArgumentException: UdtTypeName ingatlan kell állítani UDT paramétereket.
cmd.Parameters.Add (új SqlParameter ( "@fullName" SqlDbType .NVarChar).);
cmd.Parameters.Add (új SqlParameter ( "@dateModified" SqlDbType .DateTime2).);
cmd.Parameters.Add (új SqlParameter ( "@dateCreated" SqlDbType .DateTime2).);
cmd.Parameters.Add (új SqlParameter ( "@lastAccessed" SqlDbType .DateTime2).);
cmd.Parameters.Add (új SqlParameter ( "@properties" SqlDbType .xml).);
cmd.Parameters.Add (új SqlParameter ( "@size" SqlDbType .BigInt).);
cmd.Parameters.Add (új SqlParameter ( "@isDir" SqlDbType .Bit).);
cmd.Parameters.Add (új SqlParameter ( "@content" SqlDbType .VarBinary).);
SqlHierarchyId leftSibling = SqlHierarchyId .Null;
Shell32. Mappa shellFolder = shell.NameSpace (MappaElérésiÚtja);
FileStream fs = null;
foreach (FileSystemInfo FD FSI)
cmd.Parameters [ "@hid"] .Value = leftSibling = parentId.GetDescendant (leftSibling, SqlHierarchyId .Null);
cmd.Parameters [ "@fullName"] .Value = fd.FullName;
cmd.Parameters [ "@properties"] .Value = FileExtProps (fd.FullName, shellFolder);
cmd.Parameters [ "@isDir"] .Value = (FD DirectoryInfo);
cmd.Parameters [ "@dateModified"] .Value = fd.LastWriteTimeUtc;
cmd.Parameters [ "@dateCreated"] .Value = fd.CreationTimeUtc;
cmd.Parameters [ "@lastAccessed"] .Value = fd.LastAccessTimeUtc;
próbálja // Ebben az esetben nem kell az iratokhoz való hozzáférést, OpenRead () repül a kizárási
húr terek = new string ( '' leftSibling.GetLevel () Érték ..);
log.Write (szóköz + fd.FullName + + DateTime .Now.ToString () + "" ""); log.Flush ();
ha (FD FileInfo)
cmd.Parameters [ "@size"] .Value = ((FileInfo) fd) .Length;
fs = ((FileInfo) FD) .OpenRead ();
cmd.Parameters [ "@content"] .Value = új SqlBytes (FS);
else if (shallowTraversal!) spRecursive (fd.FullName, hamis TableName, leftSibling.);