This is a question that comes up a lot in the news groups.
"Why can I not restore the company on a new machine or after installing Vista?" OR "Why can't I open the company with the old company file?"
Depending on the scenario you get an error "This operation can only be performed while connected to a company on a local machine." or perhaps "Current version of the accounting application does not support this operation.".
The issue is that the company file (sbc-file) is really just a shortcut pointing to the database and computer that stores the actual data. So if you resuse the sbc-file when doing a restore on a new computer or when the computer name has changed after installing a new operating system, the file will still be pointing to the old computer. The error messages are because you cannot restore to a different computer than the one you are currently logged on to, or when you are using the Express version which does not support remote operations.
The solution to this is easy - you can edit the computer name in the sbc-file or in case of restore, simply enter a new sbc-file name in restore dialog instead of using the existing name.
This is what a company file looks like when you edit it in Notepad:
database=sampleservicecompany
server=mycomputer\MSSMLBIZ,5356
This topic came up a lot in SBA 2006 and I see it still causes some misunderstandings in places. So I thought I'd blog about it here and link to it in future news group postings.
There is no preset limit to the number of users in Office Accounting - concurrent or otherwise.
The old MSDE (used by SBA 2006) used to have a built-in performance degration when more than 5 concurrent connections were used (concurrent workload governor - a performance throttle). Note that even that did NOT translate into a maximum number of users - you could have an unlimited number of users and only if more than 5 just happened to use a connection at the exact same time would it result in a performance degration.
But there is no such limitation in SQL Express 2005 - instead they have created other limitations like; never use more than one CPU, max use 1Gb RAM, and max size of each database (4Gb).
Here's a link to a page explaining the limits of SQL Express 2005 :
http://msdn2.microsoft.com/en-us/library/ms165672.aspxIf you want to overcome those limitations you can easily use the full SQL Server 2005 instead.
In fact Office Accounting should scale very well since it relies on Sql Server - but you might find that if your company grows to more than 25 employees it could require more advanced accounting software with more features than Office Accounting.
The Loader implements a LoaderException class derived from ApplicationException similar to the way that SBA implements SmallBusinessExceptions.
Since the Loader is using reflection to call methods on the SBA objects themselves (like Logon and Initialize) it can throw both LoaderExceptions and TargetInvokationExceptions which wraps an inner exception as SmallBusinessExceptions.
Since calling applications should not be binding statically to the Loader assembly or SBA assemblies but only to the interface assemblies, they will need to catch ApplicationExceptions when using the Loader and then type cast it to ILoaderExceptions. In addition a calling application should catch TargetInvokationExceptions and check if the InnerException property is ISmallBusinessException thrown from the SDK.
Here's an example:
ISmallBusinessInstance smallBusinessInstance;
IFormsFactory formsfactory;
try
{
ISbaObjects sbaObjects = loader.GetSbaObjects(configurationFile);
smallBusinessInstance = sbaObjects.SmallBusinessInstance as ISmallBusinessInstance;
formsFactory = sbaObjects.FormsFactory as IFormsFactory;
}
catch (ApplicationException exception)
{
if (exception is ILoaderException)
{
// Handle LoaderException
}
else
{
throw;
}
}
catch (TargetInvokationException exception)
{
if (exception.InnerException is ISmallBusinessException)
{
// Handle SmallBusinessException
}
else
{
throw;
}
}
Notice that I use the "throw" here in order to not catch and hide exceptions I don't handle. Depending on your application that is often the best practise since your application cannot recover from system level exceptions anyway. If you catch-and-eat all exceptions you're basically in an unknown state after this code because you don't know if a serious exception like OutOfMemoryException was thrown - it would mean that the code would run out of memory at a random later stage (like when you later create a handle to a control) and you wouldn't know why.
Why use the Loader at all?
Well - the Loader together with the overall versioning story for SBA/Office Accounting is designed to make integration as smooth as possible and take away the big hurdles of requiring external applications to control and implement their own versioning story.
In SBA 2006 you had to find the install folder for SBA in order to use a particular version AND you had to verify that the database was the correct version for those assemblies.
But with Office Accounting you can write an external application without having to worry about what assemblies to load for a given company/database and what interfaces to use.
The external application simply binds to the desired version of the SBA interfaces (usually the latest) and all future versions of Office Accounting will always implement these interfaces (and new future interfaces). The Loader will then load the correct version of the assemblies needed to use a given database and return the necessary SBA objects like FormsFactory, SmallBusinessInstance, & ReportsEngine.
You can write an application that works with SBA 2006 and be sure it also works with all future versions of Office Accounting without having to re-release the application to your customers when a new version of Office Accounting is released.
In the following blog entries I'll go over the basics of using the Loader beginning with how to get the Loader and the SBA objects and continuing with how to launch forms and reports and save SDK objects.
The loader interface provides a method for retrieving the SmallBusinessInstance, FormsFactory, and ReportEngine for a given database.
ISbaObjects GetSbaObjects(string configurationFile);
The method also has overloads that take a configuration-object or the database and server name. The calling application will call the loader to get the SBA objects like this:
ISbaObjects sbaObjects = loader.GetSbaObjects(configurationFile);
Where configurationFile is the full path to a valid sbc-file.
The SbaObjects class contains properties for the SmallBusinessInstance, FormsFactory, and ReportEngine. The reason this class exists is that it will abstract calling applications from the internal implementation of the SBA objects – for instance in order to use the SmallBusinessInstance a Logon method must be called and in order to use the FormsFactory a call to an Initialize method has to be made. These calls are made internally in the SbaObjects class and calling applications are abstracted from knowing about them.
The loader is not strongly bound to any version of SBA and returns the objects directly without type casting them. The calling application must type-check and cast the objects appropriately like this:
// Get the SmallBusinessInstance for this database
object smallBusinessInstance = sbaObjects.SmallBusinessInstance;
if (smallBusinessInstance is ISmallBusinessInstance)
{
// Do V1 stuff here
}
else if (smallBusinessInstance is ISmallBusinessInstanceV2)
{
// Do V2 stuff here
}
// Get FormsFactory for this database
object formsFactory = sbaObjects.FormsFactory;
if (formsFactory is IFormsFactory)
{
// Do V1 stuff here
}
else if (formsFactory is IFormsFactoryV2)
{
// Do V2 stuff here
}
IReportEngineV2 reportEngine = sbaObjects.ReportEngine as IReportEngineV2;
Note that the ReportEngine is a V2 feature – calling applications will need to handle the LoaderException that is thrown when trying to get this object for a database version that doesn’t support it – i.e. when trying to get a ReportEngine when connecting to a V1 database.
The Loader is installed as a separate msi with Office Accounting. The Loader assemblies are installed into GAC including the interfaces.
Any external application using the Loader should bind to the interface assembly "ILoader.dll". An external application should never bind to the actual implementation assemblies, neither for the Loader or any other SBA assemblies.
Using reflection the external application can then instantiate an instance of the Loader class and cast it to the ILoader type defined in the interface assembly.
// Load the assembly that contains the loader object
Assembly loaderAssembly = Assembly.Load("Loader, Version=2.0.5201.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
// Create an instance of the loader
ILoader loader = loaderAssembly.CreateInstance("Loader", false, BindingFlags.CreateInstance, null, null, null, null) as ILoader;
With the above two lines of code you now have an instance of the Loader class which can be used to retrieve the SBA objects that can launch forms, work with SDK objects, and launch reports.
In this blog I will write about integrating external applications with Office Accounting.
I have worked on SBA 2006 and now Office Accounting 2007 since the beginning and one project I was fortunate enough to work on was the design and implementation of the new Loader for SBA.