Bonjour,
Je suis en train de m'amuser à faire un petit programme de GED, histoire de garder la main sur C# et SQL Server.
Pour le moment, tout va bien, ça marche à merveille.
Cependant, je ne suis pas content du tout de la façon dont j'insère le fichier dans la base de données.
En effet, pour lire le fichier, je récupère son PathName (adresse sur le serveur SQL Server) et je le récupère via un SqlFileStream.
Ceci permet de faire :
- Du traitement asynchrone si l'envie m'en prenait
- De gérer des fichiers volumineux sans devoir les charger en mémoire
- De gérer des fichiers de plus de 2 Go (bon, ça, à la limite, c'est pas tous les jours qu'on a un document Word qui fait cette taille...)
- D'utiliser convenablement le type FILESTREAM de SQL Server 2008
En revanche, pour l'insertion dans la base de données, je n'ai rien trouvé exploitant le FILESTREAM.
Voici du coup le code que j'ai trouvé sur le net (qui est le même que si je n'avais pas de FILESTREAM), et qui :
- Ne permet pas de traitement asynchrone
- Oblige à charger l'intégralité du fichier en mémoire sur le client, puis sur le serveur SQL
- Limite la taille du fichier à 2 Go
- Passe outre le flag FILESTREAM de mon champ
En gras, la partie qui me donne envie de vomir.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 using (SqlConnection cnx = new SqlConnection(@"Server=.\SQLEXPRESS;Database=MagicGED;Trusted_Connection=True;")) { cnx.Open(); using (SqlTransaction trans = cnx.BeginTransaction(IsolationLevel.ReadCommitted)) { using (SqlCommand cmd = cnx.CreateCommand()) { cmd.Transaction = trans; cmd.CommandText = "insert into document (id, title, extension, doc) values (default, @title, @extension, @doc)"; SqlParameter pTitle = cmd.CreateParameter(); pTitle.ParameterName = "title"; pTitle.SqlDbType = SqlDbType.NVarChar; pTitle.Size = 255; cmd.Parameters.Add(pTitle); SqlParameter pExtension = cmd.CreateParameter(); pExtension.ParameterName = "extension"; pExtension.SqlDbType = SqlDbType.NVarChar; pExtension.Size = 10; cmd.Parameters.Add(pExtension); SqlParameter pDoc = cmd.CreateParameter(); pDoc.ParameterName = "doc"; pDoc.SqlDbType = SqlDbType.VarBinary; pDoc.Size = -1; cmd.Parameters.Add(pDoc); pTitle.Value = fsi.Name; pExtension.Value = fsi.Extension.ToLower(); using (FileStream fs = new FileStream(fsi.FullName, FileMode.Open, FileAccess.Read, FileShare.Read)) { BinaryReader br = new BinaryReader(fs); pDoc.Value = br.ReadBytes((int)fs.Length); } cmd.ExecuteNonQuery(); } trans.Commit(); } cnx.Close(); }
Comment faire une insertion en utilisant proprement le FILESTREAM ?
Mon champ Doc est NOT NULL.
J'ai comme idée de faire comme suit :
- Insertion de la ligne avec 0x0 dans Doc
- Lecture de ma ligne insérée
- Remplacement du contenu du FILESTREAM par mon document
En suivant la méthode décrite dans cet article :
http://msdn.microsoft.com/fr-fr/library/cc716724.aspx
=> Paragraphe "Exemple de remplacement de données FILESTREAM"
En effet, le paragraphe "Exemple d'insertion de données FILESTREAM" ne fait pas du tout ce que je désire, puisqu'il se contente d'inserer dans le FILESTREAM un second document, sans pour autant créer une seconde ligne (du coup, je ne vois pas trop l'intérêt mais bon)
Y a-t-il une autre manière de procéder ?
En effet, créer une ligne vide, puis aller la modifier, je trouve ça un peu moyen pour insérer une ligne... Même si je suis dans une transaction, je trouve que ça fait beaucoup d'étapes pour pas grand chose.
Partager