views:

592

answers:

9

Hey SO'ers, I'm making a C#/WPF app that needs to access a number of tables to generate some of the xaml code I will use in the app. The tables will also contain some floating point numerical data as well.

The program is single-user, so the rdbms doesn't have to be very fancy, but the file does need to be encrypted as it will be "shrink-wrapped" and sent. I also can't force a user to install a separate program for this.

So far I've been leaning towards using an encrypted .accdb database, but am open to better options. Does using accdb require the user to have access installed?

(NOTE: I have also been looking at http://stackoverflow.com/questions/1421612/database-engine-for-a-desktop-application-in-c and )

+5  A: 

Have you looked into SQL Server Compact?

SQL Server Compact 3.5 is a free, easy-to-use embedded database engine that lets developers build robust Windows Desktop and mobile applications that run on all Windows platforms including Windows XP, Vista, Pocket PC, and Smartphone.

"I also can't force a user to install a separate program for this." - you can distribute the required files with your application.

Another solution is to use an encrypted xml file. The Dataset can very easily be saved and loaded using an xml file:

Philip Wallace
A: 

VistaDB supports xcopy (easy deployment) with full encryption, on a database or table level.

Reed Copsey
Why pay for something when SQL Server Compact is free?
Philip Wallace
It supports much more than SQL Server Compact, plus has much easier deployment. Depending on what you're trying to do, it can be a much better option.
Reed Copsey
+11  A: 

SQL Server Compact Edition and SQL Lite appear to be your main two options. SQL Server Compact has better .NET integration and Date/Time handling so I would go with that one. Also, the redistributable files are fairly low-weight (2-3MB IIRC).

SQL Server Compact will allow you to encrypt the database:

http://technet.microsoft.com/en-us/library/ms172901.aspx

...But you will have to be careful with your connection string because it is trivial to obtain an unencrypted password embedded in the client.

One last note: Selecting SQL Server Compact will enable you to use the built-in LINQ provider, which has the potential to make your life a lot easier.

Robert Venables
+1  A: 

From your brief synopsys of how you will be using this and the single user nature of it maybe an RDBMS will be overkill, you could possibly just store your small amount of data in a text/xml file and embed it as a resource in your exe (encrypted if you need to)

Tim Jarvis
I've thought a lot about doing this instead, but there are a number of relationships within the data I'm using that seem will be harder to maintain in an xml file. I'm also working under the impression that accessing data from a database file will be faster than parsing through a series of xml files
calvin
It depends on whether your data easily fits in RAM with plenty of room to spare. If so, it's only about 5 lines of C# code to decrypt *and* deserialize your entire dataset into an in-memory object tree, and another 5 lines to save it back. An in-memory object tree can do more query-wise than SQL Server et al because LINQ to Objects is significantly more powerful than LINQ to SQL or even SQL itself. On the other hand, if your data set is too big to easily fit in RAM (or may someday become so), this is not as good an option because you have to manually manage loading sections of your data.
Ray Burns
Regarding performance, if you are only going to access 1% of the data a regular database engine will usually be faster because less data will be read from disk. If you are going to access 30% or more, loading an XML file will usually be faster. Somewhere between those numbers they will perform equally, but exactly where depends on your specific situation. So again it depends on what you are doing.
Ray Burns
+1  A: 

sqlite

SQLite is a software library that implements a self-contained, serverless, zero-configuration, transactional SQL database engine. SQLite is the most widely deployed SQL database engine in the world. The source code for SQLite is in the public domain.

sqlite.phxsoftware.com System.Data.SQLite is the original SQLite database engine and a complete ADO.NET 2.0/3.5 provider all rolled into a single mixed mode assembly. It is a complete drop-in replacement for the original sqlite3.dll (you can even rename it to sqlite3.dll if you're using it natively).

the list of avilable wrappers for c# here: http://www.sqlite.org/cvstrac/wiki?p=SqliteWrappers under C# wrappers section

I'm using the one here: Simple C# Wrapper for SQLite which is basic but enough for my needs

serge_gubenko
sqlite doesn't have any decent interface to NET Framework, so it is a poor choice for a C# application
Ray Burns
that's not exectly true, to begin with http://sqlite.phxsoftware.com/ System.Data.SQLite is the original SQLite database engine and a complete ADO.NET 2.0/3.5 provider all rolled into a single mixed mode assembly. It is a complete drop-in replacement for the original sqlite3.dll (you can even rename it to sqlite3.dll if you're using it natively).the rest is here: http://www.sqlite.org/cvstrac/wiki?p=SqliteWrappers under C# Wrappers sectionI'm using "Simple C# Wrapper for SQLite" (http://www.codeproject.com/KB/database/cs_sqlitewrapper.aspx which i basic but does what I need)
serge_gubenko
Thanks for the links. I was not aware of the NET Framework wrappers people have built and had been unable to find any information about it on sqlite.org . Too bad sqlite doesn't have a "standard" wrapper that we know will be supported for many years. But that's the open source world for you.
Ray Burns
just added the links to the original post.
serge_gubenko
Thanks for the info! I spent a lot of time last night looking into sqlite and the ADO provider you referenced. I may try to use it for future projects, but I think I'm going to opt for ease of development/documentation via MS stuff over potentially smaller footprints / more efficiency
calvin
A: 

Also check out Db4o, which is an open source object database. They support encryption of the object database as well as linq which makes querying the data a breeze.

Mark
+2  A: 

This answer TOTALLY depends on your having a relatively small dataset, so consider it accordingly...

Have you considered keeping your objects in a collection and then serializing them to disk?

You can use Linq to Objects to query them in much the same way you would a database including joins, etc.

I have used this technique with a few personal projects and it works great, IF you have a small dataset.

An example is a custom membership provider I wrote for ASP.Net that uses this method if you don't have a database available (think really cheap hosted environment).

I've tested it with loads as great as 10,000 users with basically instantaneous responses (it is coming from memory after all). When I get up to 100,000 users it begins to degrade a bit and by 500,000 it is a total dog that is unusable.

You could implement your own encrypted serialize/deserialize methods.

There is a cryptographic app walkthrough at http://msdn.microsoft.com/en-us/library/bb397867.aspx

Hope this helps.

jeffa00
+1 great answer. I use this technique all the time as well. I've posted an additional answer to this question containing sample code that shows how to easily do this in a mere 29 lines of code!
Ray Burns
+1 for KISS. I use this myself frequently.
Nate Bross
+1  A: 

jeffa00 pointed out that this can be done by simple serialization if your data set isn't very large. Here is a complete working implementation to show how easy it is:

public class DataSerializer<T>
{
  static XmlSerializer _serializer = new XmlSerializer(typeof(T));
  static SymmetricAlgorithm _encryptionAlgorithm;

  public static void SetEncryptionKey(byte[] key)
  {
    _encryptionAlgorithm = Aes.Create();
    _encryptionAlgorithm.Key = key;
  }

  public static void WriteData(string filePath, T data)
  {
    using(var fileStream = File.OpenWrite(filePath))
    {
      var cryptoStream = new CryptoStream(fileStream, _encryptionAlgorithm, CryptoStreamMode.Write);
      _serializer.Serialize(cryptoStream, data);
      cryptoStream.Flush();
    }
  }

  public static T ReadData(string filePath)
  {
    using(var fileStream = File.OpenRead(filePath))
    {
      var cryptoStream = new CryptoStream(fileStream, _encryptionAlgorithm, CryptoStreamMode.Read);
      return (T)_serializer.Deserialize(Stream);
    }
  }
}

With this you can save an entire tree of objects to disk in encrypted form by simply doing:

DataSerializer<MyObjectType>.WriteData(@"c:\somewhere\something.data", myObject);

and read it back with:

myObject = DataSerializer<MyObjectType>.ReadData(@"c:\somewhere\something.data");

This is much nicer than working with SQL Server Compact or even full SQL Server, since LINQ to Objects is so much more powerful than LINQ to SQL. Faster too in many cases.

But this only works if your dataset easily fits in RAM.

Ray Burns
+1  A: 

Answer can depends on more details; yet C#SQLite (http://code.google.com/p/csharp-sqlite/) could be an option. If your database will have less that 4GB data then SQL Server Compact is a perfect candidate; no installation, no configuration, xcopy deploy.

Kaveh Shahbazian