Home | Resume | Blog Brian Ensink's Blog | Ramblings of a software developer

SQL Compact Edition files are not portable

by Brian Ensink 6. August 2011 13:12

Earlier this year my company was preparing to ship a new product. Part of the software used some new data files that would also be installed on the user's system or on the user’s network and shared among multiple users. It was convenient to put this data into a relational database so we used Microsoft SQL Compact Edition.

Our plan was to build the databases, install the files on the user system, open readonly at runtime and query the data. Everyone involved agreed SQLCE would be a fine solution. And it would have been except for one surprising problem.

If the database is built on XP or Vista/Windows 7 it simply cannot be opened readonly on the other operating system. The first time it is opened SQLCE needs to re-index the database because the National Language Support sort order is different on these two operating systems. This was a problem for us for three reasons.

  1. We install this data file (and many others) readonly. There is no need for a user to change the files.
  2. We install the data files with an elevated account. The user currently running the software may not be able to elevate to administrator.
  3. The files could be shared over a network and accessed by different client operating systems. The database would constantly be going back and forth between XP or Windows 7 NLS sort order.

Here is a Microsoft Connectentry that mentions the problem with Windows Server and Windows Mobile. The same problem exists for XP and Vista/Windows 7.

Without any known workaround for this problem I have to conclude that SQLCE databases are just not portable. Yes, they can be converted back-and-forth. Yes, that conversion will happen automatically (whether you want it to or not). But no, the data is just not usable on both XP and Vista/Windows 7 without first being converted – and then it is no longer usable on the other OS!

For us it was a show stopper. Our solution was to use Sqlite instead. Fortunately the code change was minimal because the database access layer was properly hidden behind a higher level API. Only one module had to be changed and both our software and internal tools were back up and running (hooray for good architecture!). Sqlite databases are truly portable, not just with different versions of Microsoft Windows but also with Linux and MacOSX.

Tags:

Software Development

Implementing IEnumerable<T> in C++/CLI

by Brian Ensink 4. February 2010 22:02

Most of the .NET code I write is in C# but occasionally I need to write mixed mode C++/CLI code to expose some existing unmanaged code to our new .NET code.  C++/CLI works very well for this kind of interop but the language is much less familiar to me than C#. 

For example today I wanted to implement a property on a C++/CLI class that returned IEnumerable<T> to expose an unmanaged collection.  In C# this is a very easy with the yield keyword but there is no equivalent in C++/CLI so the enumerator classes have to implemented manually.  I got hung up on the syntax and it to took me far to many google searches before finally piecing it together.  So here is a complete but simple example implementation of IEnumerable<T> in C++/CLI.

You can download the full code here.

#pragma once
using namespace System;
namespace CppLibrary
{
public ref class Earth
{
private:
ref class EarthContinents : System::Collections::Generic::IEnumerable<String^>
{
private:
Earth^ _earth;

public:
EarthContinents(Earth^ Earth)
{
_earth = Earth;
}

virtual System::Collections::Generic::IEnumerator<String^>^ GetEnumerator_Generic() sealed
= System::Collections::Generic::IEnumerable<String^>::GetEnumerator
{
return gcnew EarthContinentsEnumerator(this);
}

virtual System::Collections::IEnumerator^ GetEnumerator_NonGeneric() sealed
= System::Collections::IEnumerable::GetEnumerator
{
return GetEnumerator_Generic();
}

private:
ref class EarthContinentsEnumerator : System::Collections::Generic::IEnumerator<String^>
{
private:
EarthContinents^ _continents;
int _index;

public:
EarthContinentsEnumerator(EarthContinents^ Continents)
{
_continents = Continents;
Reset();
}

~EarthContinentsEnumerator() { }

virtual bool MoveNext()
{
_index += 1;
return _index < _continents->_earth->_arr->Length;
}

property String^ Current_Generic
{
virtual String^ get() sealed
= System::Collections::Generic::IEnumerator<String^>::Current::get
{
return _continents->_earth->_arr[_index];
}
}

property Object^ Current_NonGeneric
{
virtual Object^ get() sealed
= System::Collections::IEnumerator::Current::get
{
return Current_Generic;
}
}

virtual void Reset()
{
_index = -1;
}
};
};

private:
array<String^>^ _arr;

public:
Earth()
{
_arr = gcnew array<String^>(7);
_arr[0] = gcnew String(L"Asia");
_arr[1] = gcnew String(L"Africa");
_arr[2] = gcnew String(L"North America");
_arr[3] = gcnew String(L"South America");
_arr[4] = gcnew String(L"Antarctica");
_arr[5] = gcnew String(L"Europe");
_arr[6] = gcnew String(L"Australia");
}

property System::Collections::Generic::IEnumerable<String^>^ Continents
{
System::Collections::Generic::IEnumerable<String^>^ get()
{
return gcnew EarthContinents(this);
}
}
};
}

Tags:

Software Development

Architecture via Prototyping?

by Brian Ensink 27. January 2010 21:42

Prototyping the architecture for a large new project can be a valuable step. It can help solidify high level software architecture, measure performance, simulate different scenarios, drive further discussion, and more.  But a prototype is a poor way to convey a proposed architecture and is no substitution for a real discussion about a specific project's architecture.  Implementing a prototype is time consuming and expensive and its easy to get caught up in technical details and lose sight of the purpose.  Consider prototyping a complex client-server application, for example a MMORPG.  Seems like multiple prototypes would be involved during the project but is there any doubt that the development team would start with pencil and paper or at a whiteboard and toss around out ideas?

The question is really simple: What architecture is being prototyped?  The "what" question can't be answered by the code of the prototype itself.  Rather the "what" is the architecture concept resulting from a real discussion before any prototype is implemented.  Without that discussion even the developer doing the prototype has a hard time answering the simple question: "What is being prototyped?".  And if that is the case it is time to take a step back and just talk about the architecture.

Tags:

Software Development

About the author

I am currently a .NET developer and really enjoy the platform.  .NET seems to be able to take the developer whereever he/she wants to go.  To the desktop, to the web, to a database, etc.  At my day job I write desktop apps but I also like to toy with other tech as I have time.