Winforms Document Manager Using Filesystem & SQL Database - c#

I am trying to create a document manager for my winforms application. It is not web-based.
I would like to be able to allow users to "attach" documents to various entities (personnel, companies, work orders, tasks, batch parts etc) in my application.
After lots of research I have made the decision to use the file system to store the files instead of a blob in SQL. I will set up a folder to store all the files, but I will store the document information (filepath, uploaded by, changed by, revision etc) in parent-child relationship with the entity in an sql database.
I only want users to be able to work with the documents through the application to prevent the files and database records getting out of sync. I some how need to protect the document folder from normal users but at the same time allow the application to work with it. My original thoughts were to set the application up with the only username and password with access to the folder and use impersonation to login to the folder and work with the files. From feedback in a recent thread I started I now believe this was not a good idea, and working with impersonation has been a headache.
I also thought about using a webservice but some of our clients just run the application on there laptops with no windows server. Most are using windows server or citrix/windows server.
What would be the best way to set this up so that only the application handles the documents?

I know you said you read about blobs but are you aware of the FILESTREAM options in SQL Server 2008 and onwards? Basically rather than saving blobs into your database which isn't always a good idea you can instead save the blobs to the NTFS file system using transactional NTFS. This to me sounds like exactly what you are trying to achieve.
All the file access security would be handled through SQL server (as it would be the only thing needing access to the folder) and you don't need to write your own logic for adding and removing files from the file system. To remove a file from the file system you just delete the related record in the sql server table and it handles removing it from the file system.
See:
http://technet.microsoft.com/en-us/library/bb933993.aspx

Option 1 (Easy): Security through Obscurity
Give everyone read (and write as appropriate) access to your document directories. Save your document 'path' as the full URI (\\servername\dir1\dir2\dir3\file.ext) so that your users can access the files, but they're not immediately available if someone goes wandering through their mapped drives.
Option 2 (Harder): Serve the File from SQL Server
You can use either a CLR function or SQLDMO to read the file from disk, present it as a varbinary field and reconstruct it at the client side. Upside is that your users will see a copy, not the real thing; makes viewing safer, editing and saving harder.
Enjoy! ;-)

I'd go with these options, in no particular order.
Create a folder on the server that's not accessible to users. Have a web service running on the server (either using IIS, or standalone WCF app) that has a method to upload & download files. Your web service should manage the directory where the files are being stored. The SQL database should have all the necessary metadata to find the documents. In this manner, only your app can get access to these files. Thus the users could only see the docs via the app.
I can see that you chose to store the documents on the file system. I wrote a similar system (e.g. attachments to customers/orders/sales people/etc...) except that I am storing it in SQL Server. It actually works pretty well. I initially worried that so much data is going to slowdown the database, but that turned out to be not the case. It's working great. The only advice I can give if you take this route is to create a separate database for all your attachments. Why? Because if you want to get a copy of the RDBMS for your local testing, you do not want to be copying a 300GB database that's made up of 1GB of actual data and 299GB of attachments.
You mentioned that some of your users will be carrying laptops. In that case, they might not be connected to the LAN. If that is the case, I'd consider storing the files (and maybe metadata itself) in the cloud (EC2, Azure, Rackspace, etc...).

Related

How to put a database in the project? C#

I have the local database in SQL Server 2014 with four tables volume 1.5 GB. The essence of the program to look for in the database records with the user defines criteria. The program is written and it works fine. We should make sure that the program worked and other users who have not installed the server. How to implement this? Was a idea to serialize the data, but as I understand, it is necessary to deserialize all the data and then look for the right record.
As the comments before me already says i think you have 2 options.
Either ship the database with the client (using Sql Express or other similar solutions). That should work fine and will work without a connection to a centralized server but the size of your client package will be quite big. And if you make any changes it will only be locally, but it seems you only make reads to the database from the client?
But if i understand it correctly you install a sql server for each client, since you mention "users who have not installed the server"? Then you already have the problem with a lot of data needing to be sent out to each client, as well as the problem of updating all databases when the data needs to be refreshed.
Another solution is to allow access to the database from the client. This can work in serveral ways, if all your users is in your doman you can handle authentication based on their domain users and skip the authentication part. Then you would only need to send out the client and skip the installation of a big server and all the data.
If they are not on the domain but still on your network you could add a login on your application to allow access to the database or if you trust all your users you could add a read only account and just hardcode the login for that account.
If you want to access the data outside of a trusted environment you should of course add a separate login for each user to allow access and it might even be a good idea to use an api before the database that handles the requests from the client and then does the search to the database in a controlled manner.
I would personally go with using a centralized database to skip all the work of setting up new users and also have a single point to update when the data needs a refresh, but of course it all depends on where your users are.

How to connect ms access database from network drive

I have tried to connect to MS access database on a network drive from windows application.
My connection string is:
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=\\dtinaurdsna02\\LE-IN
\\Data_Analysis\\Quality_Rating_Tool.accdb
It's working on my system but it is throwing error on other systems (they have access to this network drive).
Microsoft Access database is designed to optimally work for one user at a time. You can get around some of these limitations by linking the database.
Excerpt from Access Database Best Practices
Avoid Multi-User Collisions: If you store all your objects in one file,
including your tables, Access will usually have difficulty when
multiple users attempt to open the same database file. While Access
does have record-level locking, you may still receive errors that
another user is currently in the database and you cannot make changes.
To avoid this, you provide each end user with their own front-end
database file, each linked to the same Access Data File.

Recommendations For Saving Files in Elastic Beanstalk

I have an ELB application that we have just added photo upload functionality to. Currently this saves the images in a folder within the deployment directory in ELB, saving the URL to a DynamoDb table. Everything works fine. Whenever a user wants to see an image we simply attach the URL to the src attribute of an tag in the UI and the browser downloads the image directly.
However it occurred to me that if the underlying EC2 instance is terminated and re-started we will most likely lose all the photos. Am I correct in this assumption? If so, what's the best practice here? Should uploads always be saved in an S3 bucket? Any guidance hugely appreciated.
Should uploads always be saved in an S3 bucket?
TL;DR
In an elastic cloud environment, yes always move your static content to reliable external storage (in this case S3). It will make your app scale better. See the S3 question here
Resources:
IAM Credentials Giving your app keys to access s3 right out of the box in Beanstalk.
S3 Getting Started
Media Reference Architecture Describes at least part of what you're looking for. Look at the S3/Datastore/Web Server interaction there. More here.
Longer Description
In a traditional architecture you might have a drive attached to a web server or two and you store the files there. You always expect those to be up. If you run out of disk space you have a problem. If you're server craps out, you've also got a problem. Even if you have a backup, you run the risk of both going down and you needing to restore all your data AND bringing up a server manually.
In a cloud architecture you're basically admitting that the "machine" is fallible and no longer relying on it to store any application state. It should be used to store things you need on disk to launch the app and/or temporary storage, but if you need something long term thats why services like S3 exist! By eliminating state from your app servers you can scale them automatically (however you see fit) without worrying about your users' content. If you had other services that needed that content, they could get it from there as well with the proper permissions.

Solution for a no-server multi-user application/database?

I am at a dead end an I could really use some help.
I intern for a huge company. My projects involves creating an application to automate/simplify the work of a retiring employee.
The problem here lies in the strict company policies. I am a developer stuck at business end of the company. Therefor IT gives me nothing:
I don't have a server (nor web nor database)
I can't create a server, because no pc will be running and we can't keep them logged in due to single sign on with company cards.
I can't install anything on the pc's in the network.
I can access a share file server, that is backed up every day.
The libraries involved have to be free
A central database has to be accessed by a dozen of users (at once)
The database will recieve new data every day and will grow accordingly
The users will both read and write from/to the database
Preferably C#.NET or WPF solution
Application needs to open files stored on the shared drive. ( Only once, the important information will be extracted and stored in the database.. the file will then be removed)
My initial idea was to use silverlight (which runs standalone) in combination with SQLite. I ran a test and Silverlight files stored on the shared drive work. (Silverlight is installed on every pc on the network) This is my preferred front end. However (correct me if i'm wrong) I tried SQLite-net and I needed to add the sqlite3.dll to my windows/system32 folder, but on the network PC's I don't have access to the Windows folder, so this can not be done.
Also I read that SQLite or files in general can become corrupt when accessed by multiple users as one, so maybe I thought locking was an idea.
Which solutions are there to my problem?
I worked for a company for several years writing software for police departments to manage traffic collision reports. Police stations usually have little-to-no IT support, so we faced many similar limitations. The company actually did pretty well using Microsoft Access databases, with the setup looking something like this:
The shared drive had an Access database file (.mdb or .accdb) which was the actual "database".
Client computers (at the officers' desks) had Access applications with local "utility" tables for temporary storage, UI defined in Forms, and logic defined in Modules. Each of the client machines were connected to the repository on the shared drive by using linked tables. Local client configuration was stored either in the Access application in a config table, or in a text file on the machine.
It's not the cleanest solution, but it would allow you to create and maintain a unified solution using files that don't need to be installed and don't require any funny permissions, as long as everyone has read/write access to the shared drive.
Create a website. Today you can host ASP web apps in a stand alone .exe. By doing so you can make sure that the shared files are only accessed by one process. You can also limit the access to sqlite.
It also means that you do not have to distribute anything. Simply start your application and tell your users which url and port they have to browse too.
As for permissions, only the account running your webhost requires access to shared files etc.
You should take a look at ScimoreDB. It's an embedded database that supports multi-process read/write access. If needed it can also act as a client/server database; even as a distributed database with multiple nodes.
It's free to use and deploy. It has support for C++ and .NET. Only disadvantage is that it only works on Windows.

Correct way to handle roaming data storage with C# in Metro?

I'm creating a C# Metro/Modern UI app, and I need a way to handle some user data (mostly just small strings, but a fair amount of them), and specifically I'd like the data to 'roam' with a user's Microsoft Account. I know that you can handle this with roamingSettings, but it seems like that's supposed to be used more for like storing user IDs and other one-time settings, whereas I would be using it to store all of my app's data, and there seems to be a limit to the amount of space I get with that. I was thinking about using SkyDrive to host a "MyApp Data" folder, but I can't seem to figure out how to upload a simple text file to it :(
It seems like the best way to handle it would be to set up an account on Azure or EC2 and then make a simple PHP API so I could access the SQL database from my app, but I'd rather not have to pay for hosting.
I've seen other questions about Metro app storage on StackExchange and Microsoft's own forums, but most of those are in reference to local storage and using SQL servers to handle the storage.
So should I just use roamingSettings and keep an eye on the quota, should I try to use cloud hosting, or is there a better solution I just haven't thought of yet?
Thanks!
A few things about roaming settings:
- they are intended for that, settings. Not as a data replication scheme, thus the quota
- they are not immediate. You can create a setting named "highpriority" that will replicate in less than a minute, but other settings can take several minutes to replicate. If you need data to be available immediately, roaming settings are not an option. Also, if you exceed quota all your data will stop replicating, which is a bad thing. :) It also will not replicate between different versions of your app even if the settings are the same. In addition, if you do not use the app for a period of time (default is 30 days), then the roaming data will be deleted from the cloud. I am pretty sure roaming data can also be turned off via group policy in enterprise settings.
You can leverage SkyDrive. Make sure you download the Live SDK. Overview of using SkyDrive is here... http://msdn.microsoft.com/en-us/library/live/hh826521.aspx It is, fundamentally, just a collection of REST APIs. See the SkyDrive photo sample for an app that uploads files to SkyDrive http://code.msdn.microsoft.com/windowsapps/Live-SDK-Windows-Developer-8ad35141
I would go for a cloud based solution. A MS employee told me that the roaming data is a "best effort" there is no control if it actually works, sometimes it works, sometimes it just doesn't.
Personally I'd try to use the skydrive option

Categories