Det kan undertiden være nyttigt at skulle gemme filer i SQL Server. Før SQL Server 2008 havde man den mulighed at gemme filer i en BLOB, dvs. man gemte filen binært i en kolonne af type VARBINARY. Flere har talt imod denne løsning, fordi den – i hvert fald hvis man skal tro rygterne – kunne være ekstremt skadelig for performance. Flere anbefalede i stedet en løsning, hvor filerne fysisk bliver gemt på disk på et fileshare, og man i stedet nøjes med at gemme filens placering i en kolonne på SQL Server. Det er naturligvis en lidt skrøbelig løsning, fordi man altid skal huske at opdatere fileshare og database som ét. Det kan gøres i en transaktion, men det er indiskutabelt en lidt besværlig løsning.
Til det formål introducerede SQL Server 2008 type FILESTREAM. Med FILESTREAM gemmes filerne fysisk på disk et sted, som SQL Server administrerer, men al tilgang til filerne går gennem SQL Server med T-SQL.
FILESTREAM er som default ikke tilgængeligt på en nyinstalleret SQL Server, så der skal en lille smule arbejde til for at kunne benytte det.
Vha. ADO.NET kan man læse og skrive til en FILESTREAM kolonne. Det er ikke svært, men det kræver lidt arbejde, hvor man skal have fat i mindre fashionable ting som SqlFileStream og GET_FILESTREAM_TRANSACTION_CONTEXT. Desuden er der krav om, at både læsning og skrivning omkranses af en transaktion, som man selv er ansvarlig for at oprette. Alt i alt kunne man godt ønske sig, at der var en lidt mere elegant måde at gøre det på.
Heldigvis findes der en sådan elegant løsning (ellers ville jeg ikke have noget at skrive om), og den findes i Entiry Framework.
Givet følgende tabel med en FILESTREAM kolonne,
1: CREATE TABLE Ad
2: (
3: AdId UNIQUEIDENTIFIER NOT NULL ROWGUIDCOL PRIMARY KEY,
4: UserId UNIQUEIDENTIFIER NOT NULL,
5: Photo VARBINARY(MAX) FILESTREAM NULL,
6: Url NVARCHAR(512) NOT NULL,
7: ExpiryDate DATETIME2 NOT NULL
8: )
vil Entity Framework automatisk bl.a. generere en property Ad.Photo af typen byte[]. Bemærk i øvrigt, at en tabel, der benytter FIILESTREAM, skal have en ROWGUIDCOL kolonne. Som i gamle dage er kolonnen med filen stadig af typen VARBINARY, men med et ekstra lille FILESTREAM bagefter, som sørger for al den filbaserede magi.
Med Entity Framework kan man nu gemme sine filer i SQL Server meget nemt ved blot at omsætte sin fil til et byte array:
1: using (var db = GetContext())
2: {
3: Stream fs = File.OpenRead(filePath);
4: using (var reader = new BinaryReader(fs))
5: {
6: var ad = new Ad()
7: {
8: // Set other properties here.
9: Photo = reader.ReadBytes((int) fs.Length)
10: };
11: db.Ad.AddObject(ad);
12: db.SaveChanges();
13: }
14: }
På tilsvarende vis kan filer læses meget simpelt. Entity Framework sørger for alt det beskidte arbejde.