Make last change to database when program has crashed/been terminated? - c#

I have an app where user can work on a file downloaded from database. When file is downloaded, in database query is run setting "owner" value in corresponding table row. As a result other users see that file is owned by somebody else and can only read from it, not modify it. After work session user saves file to database and sets "owner" to none allowing other users access file. This works fine till app crashes or there is power shortage or some error in system that terminates app leaving database entries "reserved". In case of crash I can follow this approach :
WPF global exception handler
and try to connect to database to "free" all files reserved by user, but in other cases as my research has shown there is no way how to know that program failure has occured and I should "free" database so other users can access previously reserved files. Is this way how to show other users that something in database is not awailable for editing is in general bad design or there are solutions to this type of a problem?

Related

Using dialog Windows in SQL external procedures

I wrote dll for my SQL database which takes BLOB data from tables and converting it into pdf file. It works good, but i try to add dialog window for choosing pdf saving path and it gives me next message:
System.InvalidOperationException: Showing a modal dialog box or form when the application is not running in UserInteractive mode is not a valid operation. Specify the ServiceNotification or DefaultDesktopOnly style to display a notification from a service application.
May be someone know what's problem?
dll code where issue is:
public static void Run(SqlInt32 i)
{
FolderBrowserDialog fd = new FolderBrowserDialog();
fd.ShowDialog();
string save_pth = fd.SelectedPath+'\\';
if (gener_pdf(gener_jpg(i, save_pth), save_pth))
{
List<string> to_del = gener_jpg(i, save_pth);
for (int p = 0; p < to_del.Count(); p++) { File.Delete(to_del[p]);}
}
}
The exception message already tells you quite precisely what the problem is:
Showing a modal dialog box or form when the application is not running in UserInteractive mode is not a valid operation.
As pointed out in the comments, SQL Server is not a user interactive process; it's a service.
You say that you "need" to do this (presumably, that you need to show the user a dialog box to choose the save path), but quite simply, doing so is wrong on every level. Not least of which being that, as also pointed out in comments, it's extremely unlikely that anyone will be logged in to the machine running the SQL Server process, so there's no one to respond to the dialog prompt.
There are apparently ways to display a dialog box from a non-user-interactive process, but that still assumes that someone is waiting for it to be displayed on (in this case) the database server machine. The odds of this appear to be slim.
Reconsider what you are trying to do, and how. If you absolutely need the user to provide a location and file name on the database server to which to save the generated report, gather that information up front via whatever UI they're working with instead of during the execution of the database code.
More likely you should just put the PDF somewhere (anywhere) with a randomly generated name (which in turn is stored in the database), or even as simply a binary blob in the database, and then offer the user a way to download the PDF thus generated via whatever interface you already have for the user to interact with the data. Doing so will completely circumvent the problem, while maintaining a clear layer separation.

Permanently add a database to an application C#

I'm trying to create software that will add a computer to an Active Directory domain. One criteria I need to meet is the machine must be added to the proper OU. In order to do this I have a set list of site locations with addresses (this is how we determine OU). This list is currently in the form of an ACCDB file, and I want to include this within the application as the Access list will not be changed.
Everything I see wants the DB file to be connected to in a different location such as server or on the local machine. My preference is to use the DB file as a reference or something inside the program's .exe file itself. I may be missing something horribly obvious, but it's been messing with me for a couple days so I'm reaching out for help.
To clarify, this software MUST be self contained (no installer). It must also be able to determine the proper OU to join to the domain (no access to shares until the PC joins the domain). It must also be user-friendly enough to avoid mistakes, meaning I want to avoid copying distributing multiple files that must go to a correct location. This is why I want to embed the ACCDB file into the application for on the fly use.
Things get much easier because this is static data. You don't have to worry about persisting this data, reclaiming changes into your program, or users accidentally deleting something, etc. You will be able to just use an embedded resource in your application. In the link, follow the examples using the image file. Text file examples will corrupt your database.
However, there is still a trick to doing this. The problem is the Access engine included with Windows will not be able to open the database as a resource, and so you will need to save this file to the local hard drive. The good news is its not as bad as it seems, because your program can do this as needed, and make sure it's right, rather than asking the user to put a file in a specific place.
As for where to put the file when you extract it... the safest and best place is the Application Data folder. You can easily get the path for this folder by checking the results of this call:
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
This will give you a path where standard privilege users do have write access, no matter which user.
In summary:
Embed the ACCDB as a resource.
When your program runs, get the Application Data path using the Environment object.
Open a FileStream for writing to a file based on the path from #2
Open the embedded resource as a Stream object in C#
Copy the stream from #4 to the stream from #3. Make sure to use a mechanism intended for binary data, rather than text.
Close/Dispose your streams, so no locks remain on the file. This is as simple as putting using blocks in the right places.
Open a normal Access connection to the file you just made, using any of the thousands of tutorials or examples available on the web as a guide.
In this way, you only need to distribute the final .exe file, and users won't need any special permissions to use the database. You don't have to worry if a user deletes your file; it's still embedded in the application, which will recreate it if needed every time it starts up.
The downside is a clever user may be able to manipulate the database to end up in an undesirable OU. If you need to worry about this, you should consider having the program check a web service, rather than using embedded data. Anything you embed can ultimately be altered by an end user. A web service is also nice because you can update your mapping data as your organization evolves, without needing to rebuild or redistribute the program.

Running number with multiple instance C# program

I would like to check with you all regarding running multi-instances of same program (in different PC) with a running number (non-duplicate) field on it.
Program outline
- Program will get running number from DB (Eg: LoanID from LoanRef table)
- User input info and click on Save.
- Program will save the information to DB (eg: Loan table)
Currently, the program will retrieve the latest running number from DB (SQL Server 2012) and put it in read only text filed on the program.
During my development testing, I only tested with one program on one PC and it worked fine.
When I tested with multiple PC, access (almost) at the same time, the running number become a problem.
Is there anyway to prevent such kind of running number issue (while allowing multiple instances of the same program).
I think of generate the number at the end of 'Save' process but the problem is user wants to see the number before save. So, I need to get it when form load occurs.
And I also can't disable multiple instances with Mutex because more than one person needs to use this program.
Any idea on what functions or features that I should use or check?

Logtool for desktopapplication

I've created this small tool in C# that deletes a record in a database. So instead of opening and writing SQL I now just enter the specifics and the small application deletes it for me.
But now I need to allowe everyone access to this small application. So I need a way to log what they user deleted (recordid and stuff). Could I just plainly do a write to file? What happens if two or more users are using the application at the same time?
The question might be what exectaly you want to achive. where you want to write log into sql database or into files. or you want to send an email to your self or somebody else. if you have one of these question in your mind. just use LOG4NET
What you have to do is use this utility into your application and add its logging into desire location.
if you want to log into sql server what you can do is use Delete trigger in your tables and log what users have deleted.

Prevent overwriting Database when updating ClickOnce Application

I finished my c# Click once application, so I published it.
The problem with it is, that I'am using a small SQLite database, for keeping settings and a lot of other small things, which will get overwritten by the new SQLite database, every time I update my application.
There are settings in the database like: Remember password and Remember username, there is also a counter, that counts how many times the application has been started. All of that will be lost and the user will have to fill in his username and password again, even if he checked the boxes to remember, because the database will be overwritten.
Question: How do I prevent to SQLite Database from getting overwritten in my Click Once application?
I used the following link to solve my problem:
http://robindotnet.wordpress.com/2009/08/19/where-do-i-put-my-data-to-keep-it-safe-from-clickonce-updates/
This article explains how I can create my Database in the roaming folder of AppData, create a folder there called like your company name or the name of your application and put the Database in that folder.
You should have "Template" database which will always override and created database with data which will not override after installing of new version of application.
The database with data should be created if it doesn't exist at startup of application.

Categories