Totali 201
Anonimi 201
Registrati 0

Username
Password
   
Ricordami
  Ho perso i dati   Nuovo utente        
Cerca
























 



 

SharpDocumental. Un sistema di archiviazione e gestione documentale in C#
     
 

SharpDocumental. Un sistema di archiviazione e gestione documentale in C# (piattaforma documentale, document management )
Ideata e realizzata dall'Ing. Lorenzo Banderali.

Introduzione alle piattaforme documentali

Sharp Documental è una piattaforma documetale interamente scritta in C#, ed utilizza un database SQL per la memorizzazione dei documenti e dei dati in genere.
 Una piattaforma documentale, come Sharp Documental, è un sistema in grado di gestire documenti ed immagini, quindi di memorizzare dati strutturati, di poterli creare, modificare, cancellare e cercare.
Ovvero il sistema supporta le funzioni base "CRUD": CReate, Update e Delete, insieme ad altre.
La piattaforma documentale è multi utente, ovvero più utenti contemporaneamente possono accedere ai docuemnti e gestirli in autonomia.
Uno dei punti di forza è la gestione delle modifiche ai documenti attraverso un sistema di versionamento, per cui è possibile recuperare le versioni precedenti di un documento, anche di prendere in "checkout"
un documento per poi aggiornarlo e rilasciarlo tramite un "checkin" o un annullamento del "checkout". Questo sistema non consente ad altri utenti di effettuare modifiche al documento fino a che questo è in "riserva" ovvero in checkout da parte di un'altro utente. Ciò scongiura dall'effettuare modifiche in concorrenza e di gestire il merge o di evitare la perdita delle modifiche di un'utente (tipicamente quello che lo rilascia per primo, perchè senza un sistema di controllo tutte le modifiche effettuate da parte del primo utente andrebbero sovrascritte dall'operazione di aggiornamento effettuata dal secondo utente).
I documenti sono in concreto, un insieme di contenuti e di proprietà, dette "indici" che lo caratterizzano e ne consentono la categorizzazione e la ricerca. Gli indici possono essere di diversi tipi: stringhe, interi, booleani, date, etc...
Tutti documenti sono tipizzati, ovvero sono istanze di una classe documentale che ne definisce gli indici. Le classi documentali sono quindi insiemi di definizioni di indici intesi come "nome" e "tipo", mentre il "valore"  fa parte solo dell'istanza della classe ovvero dei documenti. Si può pensare alle classi documentali come template o moduli cartacei in cui l'utente potrà scrivere dei dati in caselle predefinite ed in formati preconfigurati. Sono previsti anche valori di default ovvero valori automaticamente inseriti qualora in fase di creazione del documento non siano specificati.
Le  classi documentali possono ereditare da altre classi, ovvero possono estendere gli indici definiti da altre classi (con ereditarietà singola e senza override).
Ovvero, a titolo di esempio, la casse "C1" definisce un indice "I1". La classe "C2" viene creata indicando come classe base la classe "C1" e definendo un indice "I2". La classe "C2" possiederà non solo l'indice "I2" definito per la stessa, ma anche l'indice "I1" definito dalla classe ereditata "C1". E' possibile creare gerarchie complesse di classi legate da ereditarietà.

Architettura della piattaforma

Sharp Documental è un sistema composto da più parti. Un application server che si occupa di intefacciarsi con il database, di elaborare i dati e di interagire con i clients attraverso dei webservices.
Il sistema può essere rappresentato dall'immagine seguente:

 

L'utilizzo dei webservices consente di potersi connettere facilmente all'application server utilizzando reti internet o aziendali.
Sia l'application server che i clients sono formati da più moduli.
L'application server è costituito da due moduli. Un modulo "DatabaseInterfaceLib"  si occupa di interfacciarsi con il database ed internamente è suddiviso in tre parti: la parte di accesso ai dati (basso livello), di elaborazione dei dat, ovvero la logica di business e l'interfacciamento con altri moduli tramite esposizioni di API. Un'altro modulo "SharpDocumentalWeb" in realtà una soluzione web, connesso al modulo precedentemente descritto, consente l'esposizione dei webservices verso i clients.
I clients sono costutuiti anch'essi da due moduli. Il primo "SharpDocumentalClientLib" è un interfaccia verso i webservices, anche questo suddiviso in tre layer (3-tier). Il secondo "SharpDocumentalManager" è un'interfaccia grafica che consente di gestire il sistema.
Questo modulo è "opzionale" nel senso che le API esposte dal modulo "SharpDocumentalClientLib  sono utilizzabili da qualsiasi progetto o modulo sviluppato dall'utente: non solo una libreria di classi, un applicativo, ma anche una web solution.

Caratteristiche della piattaforma

Sharp Documental offre le seguenti funzionalià:

- Multiutente (gestione token autenticativi)
- Creazione e gestione di classi documentali
- Erdeitarietà delle classi documentali
- Creazione e gestione di indci (proprietà delle classi documentali
- Diverse tipologie di indici (stringhe, numeri reali, interi, date etc..)
- Valori di default per gli indici
- Creazione di documenti
- Modifica documenti
- Cancellazione documenti
- Versionamento dei documenti (minor e major version)
- Meccanismo di gestione concorrenze tramite operazioni di chackout, checkin ed undo-checkout
- Gestione multicontent (ovvero più contenuti per un documento)
- Ricerca documentale
- Ricerca documentale in base ad: indici, contenuto, classe documentale, caratteristiche documento (es id), etc....
- Ricerca tramite query "libere" e complesse definite dall'utente.
- Ricerca full-text
- Lettura ed estrazione di testo da documenti, per la ricerca full-text. Formati supportati. Testo (.txt), Acrobat PDF (.pdf), Word (.doc, .docx), Excel (.xls, .xlsx).
- Interfacciamento tramite Webservices ed API.
- Applicativo di amministrazione
 

 

 
 Applicativo di amministrazione SDEM (Sharp Documental Enterprise Manager)

Sharp Documental offre un'applicativo per la gestione dei documenti.
Tale applicativo è costituito da un pannello di menu, collassabile tramite il quale è possibile accedere a tutte le funzionalità del software.
In dettaglio:

Login. Autenticazione all'applicativo.

Gestione degli utenti:

Visualizzazione - Modifica utente:

Classi documentali

Indici (proprietà) delle classi documentali

Modifica

Creazione di un documento: selezione della classe documentale

Creazione di un documento: valorizzazione indici

Creazione di un documento: inserimento content/s

Creazione di un documento: conferma

Modifica di un documento

Folder e document explorer

 

Visualizzazione di un documento: informazioni generali

 

Visualizzazione di un documento: proprietà

Visualizzazione di un documento: contenuti

Visualizzazione di un documento: versioni

Ricerca documenti

Casella di ricerca (con suggerimento nomi, indici, operatori)

Ricerca fulltext


 Struttura del database

Lo schema seguente mostra la struttura del database:

Il database utilizzato è MS SQL 2005. La struttura del database è piuttosto scarna, chiara e totalmente autoesplicativa.
I valori "value" nella tabella DocumentsProperties sono di tipo stringa, anche per i valori delle proprietà di tipo double, integer etc...
Per semplicità e performances è stato scelto di utilizzare una sola tabella con un sistema sofisticato di conversione dei dati in modo che possano essere fatti confronti per le query.
Il confronto tra le stringhe, tipo in cui sono convertiti tutti i valori degli indici, tiene conto della lunghezza delle stringhe.
Ne deriva che rappresentando in modo "classico", ad esempio un double, attraverso un formato stringa il valore 12.001 risulta  maggiore del valore 120, ma erroneamente !
Per ovviare a questo problema la soluzione è quella di utilizzare più tabelle, ciascuna per tipologia di valore (e con "value" tipizzato") oppure convertire i dati non in formato stringa in un formato confrontabile durante le ricerche.
Si è scelto ad esempio, nel caso dei numeri reali double, di convertire i valori con un formato a lunghezza fissa e con virgola in posione fissa.
Il valore double 12.001, semplificando, sarà convertito in "000000000012,0010000000". Quando viene effettuata una query ad esempio inserendo select .... where propval > 120 il parser della query convertirà questo valore in "000000000120,0000000000" e la ricerca si comporterà in modo corretto. Questo metodo è estremamente performante ed ha l'unico svantaggio di dover per forza effettuare il parse delle query, comunque necessario per svariati motivi, logici ed implementativi, ovvero principalmente per mascherare la struttura del database all'utente.
 

Ricerche

Le ricerche rappresentano la parte più complessa del sistema e sicuramente la più interessante dal punto di vista tecnico, oltre a rappresentare spesso una funzionalità fondamentale da offrire agli itenti
Le ricerche avvengono specificando una query in formato testo, in modo tale che possa essere facilmente customizzabile.
La struttura della query che l'utente può richiedere è convenientemente semplice e deve mascherare la relativa complessità e specificità implementativa del database.
Si è definito un formato di query semplice, flessibile e potente che viene convertito da un parser in una query da effettuare sul database (invisibile se non per diagnostica all'utente).
Un esempio è il seguente:

SELECT DocumentID,DocumentCreatorID,DocumentCreatorName,DocumentCreationDate,DocumentLastModifierName,DocumentLastModifyDate,DocumentLastModifierID,DocumentMajorVersion,DocumentMinorVersion,DocumentRootID, DocumentISCurrent, DocumentFolderID,DocumentFolderName FROM documents WHERE DocumentISCurrent='Y' AND DocumentRootID IS NOT NULL  AND TestPropBase = 'test' AND ContentText is not null   ORDER BY DocumentID desc

che viene parsata e trasformata in

SELECT DISTINCT docs.ID AS DocumentID ,usrCr.ID AS DocumentCreatorID ,usrCr.UserName AS DocumentCreatorName ,docs.CreationDate AS DocumentCreationDate ,usrMod.UserName AS DocumentLastModifierName ,docs.LastModifyDate AS DocumentLastModifyDate ,usrMod.ID AS DocumentLastModifierID ,docs.MajorVersion AS DocumentMajorVersion ,docs.MinorVersion AS DocumentMinorVersion ,docs.RootDocument AS DocumentRootID , docs.[CURRENT] AS DocumentISCurrent , docFolder.ID AS DocumentFolderID ,fld.FolderName AS DocumentFolderName  
FROM ClassTypes_Properties classTP
INNER JOIN PropertyTypes propTypes ON (propTypes.ID = classTP.Property)
INNER JOIN DocumentsProperties docProp ON (classTP.ID = docProp.PropertyID)
INNER JOIN Documents docs ON (docProp.DocumentID = docs.ID)
INNER JOIN ClassTypes classTTP ON (classTTP.ID = classTP.ClassType)
INNER JOIN Users usrCr ON (docs.Creator = usrCr.ID)
LEFT OUTER JOIN Users usrMod ON (docs.LastModifier = usrMod.ID)
LEFT OUTER JOIN Documents_Folder docFolder ON (docs.ID = docFolder.Document)
LEFT OUTER JOIN Folders fld ON (docFolder.Folder = fld.ID)
LEFT OUTER JOIN [FullText] ft ON (docs.ID = ft.DocumentID)
WHERE docs.[CURRENT] ='Y' AND docProp.DocumentID IN (SELECT DISTINCT docs.ID
FROM ClassTypes_Properties classTP
INNER JOIN PropertyTypes propTypes ON (propTypes.ID = classTP.Property)
INNER JOIN DocumentsProperties docProp ON (classTP.ID = docProp.PropertyID)
INNER JOIN Documents docs ON (docProp.DocumentID = docs.ID)
WHERE docs.RootDocument IS NOT NULL ) AND docProp.DocumentID IN (SELECT DISTINCT docs.ID
FROM ClassTypes_Properties classTP
INNER JOIN PropertyTypes propTypes ON (propTypes.ID = classTP.Property)
INNER JOIN DocumentsProperties docProp ON (classTP.ID = docProp.PropertyID)
INNER JOIN Documents docs ON (docProp.DocumentID = docs.ID)
WHERE (classTP.PropertyName='TestPropBase' AND docProp.[Value] = 'test' ) ) AND docProp.DocumentID IN (SELECT DISTINCT docs.ID
FROM ClassTypes_Properties classTP
INNER JOIN PropertyTypes propTypes ON (propTypes.ID = classTP.Property)
INNER JOIN DocumentsProperties docProp ON (classTP.ID = docProp.PropertyID)
INNER JOIN Documents docs ON (docProp.DocumentID = docs.ID)
LEFT OUTER JOIN [FullText] ft ON (docs.ID = ft.DocumentID)
WHERE ft.Text is not null  )
ORDER BY docs.ID desc

Utilizzo del codice

Il codice in allegato è utilizzabile a scopi non commerciali. Non è possibile distribuirlo modificando il tipo di licenza o senza indicare la fonte.
E' possibile modificare il codice sorgente. E' gradito l'invio di un feedback a solchiere@gmail.com per segnalare bugs o migliorie effettuate.

Declino ogni responsabilità per eventuali danni arrecati attraverso l'utilizzo del software in oggetto.
L'utilizzo del software è condizionato dalla completa accettazione delle seguenti condizioni:
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.



Download

Scarica la soluzione completa (130 MB)
 
 

 
Commenti degli utenti:

Scrivi un commento
     
 
Autenticarsi per inserire un commento

Label