Dailycode.info

Short solution for short problems

Self tracking entity update not working or not purged to the database

If for some reason (Working with decoupled layers, eg. WCF) the update is not purged to the database by using self tracking entities and the entity framework, you can try this to solve it:

in stead of writing this code:

deploySettings.MarkAsModified();

deploySettings.Modified = DateTime.Now;

deploySettings.ModifiedBy = userName;

deploySettings.UpdCount = deploySettings.UpdCount + 1;

deploySettings.AcceptChanges();

 

Write the code like this:

deploySettings.MarkAsModified();

deploySettings.Modified =DateTime.Now;

deploySettings.ModifiedBy = userName;

deploySettings.UpdCount = deploySettings.UpdCount + 1;

ents.GP_MES_Deploy.ApplyChanges(deploySettings);

 

Last off course save the changes

ents.SaveChanges();

In my case I was sending over my self tracking entities to iOS over SOAP. The self tracking was then not working. So the context did not find the changes. 

 

 

 


Entity frame work with self tracking entities database changes.

There are many ways to implement the entity framework. I chose to add a link to the template in a different project. This implementation can be found here.

Now this article doesn’t describe in detail what to do when the database changes. This can be a very pain full operation if you have to figure it out yourself. That’s why I wrote this post.

In this case I chose to change an existing database table and add a new table to the database.

I divided the solution in 3 layers, the database layer, a process layer and a GUI. In between you’ll find the entities going from top to bottom. So no use of DTO or any kind of mapping.

 

The edmx model is located in the DataLayer. Also the generated tt files for the self-tracking entities is located there.  In the CMDBProcessLayer  I added the context as link and in the CMDBentities project I added the self-tracking objects as linked files.

Let go to the update process.

Step 1 is off course update the database.

Step 2: Remove the linked files to the entities and the context.

 

 

Step 3: Update the database model (edmx file)

before:

 

after: (Do not forget to save the model, else you could get problems creating the code generation items)

 

Step 4: Delete the old tt files in the DataLayer

 

Step 5: Generate new tt files

 

Step 6: Turn off code generation on the entity model.tt file

 

Step 7: Delete all remaining file generated by the entities.tt file:

 

Stap 8: repeat step 6 and 7 for the context.tt file

 

Step 9: Add the Entity.tt file to your entities shared projects. (If you do not see the files, choose 'All Files' in the file filter box on your lower right.)

 

Step 10: add the context.tt file as linked file to the process layer

 

Step 11 (Last step): Change the namespace of context.tt file to the namespace of the shared entities project.

 

Now you can build and you have the new data structure.

 


Self updating windows program part 2

In part 1 I explained how to write and implement a self updating windows program. The functionality was simple. Just before I close the program to be updated, I open the “update.bat“ file. Then I close the program. The bat file first pings to create a delay and after the ping it copies the new files to the directory. When its finished it will open the application again.
 
Because the interaction with the user is not so great, although I did not receive any complaints, I decided to improve this part of the application.
 
After some thinking I came up with the idea to create an updater program which can be used for multiple programs. So it had to be configurable.
 
 
 
The only thing you have to do is to copy the updater.exe and its configuration file to your solution. Make sure it is copied to the bin folder. Just add it to your solution and right-click on the files and choose properties. Then you will see the property copy to output directory. Set this property to: Copy always. Then you fill in the path in the configuration file. The configuration file could look something like this:
 
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="UpdateFilesPath" value="\\fileserver\updates\myprogram\latestversion\"/>
  </appSettings>
</configuration>
 
Then in the directory where the new files are placed, you’ll have to add an XML file called:updateInfo.xml with the following format:
 
<?xml version="1.0" standalone="yes"?>
<UpdateInfoDS xmlns="http://tempuri.org/UpdateInfoDS.xsd">
  <UpdateInfo>
    <ApplicationName>MyProgram</ApplicationName>
    <NewVersion>2.1.1.2</NewVersion>
    <ExtraInfo>Test version for update</ExtraInfo>
    <DeletePrevVersion>false</DeletePrevVersion>
  </UpdateInfo>
</UpdateInfoDS>
 
So here we can set the parameters of the updater. The new version and extra info parameters are simply to inform the user during update about what is being updated. The application name is shown on the tool as well, but is also used to check if the program to be updated is still in use. So it is important this is exactly the same is the exe you are trying to update.
The delete previous version (DeletePrevVersion) parameter is like it suggests: deleting all the files of the previous version.
 
To check if a new version is needed and to start the updater is similar as in part 1, but I will explain it again:
 
Because I’m working on a network with a database, I’ll check the database for a new version:
 
Assembly asm = Assembly.GetExecutingAssembly();
//Check registration and version
if (CheckRegistration(asm.GetName().Version.ToString()))
  
If there is a newer version then the current version of the program I will start an update:
 
System.Diagnostics.Process.Start(Application.StartupPath + @"\Updater.exe");
 
After I started the updater program, I’ll write some information to the database and close the application. The updater will wait until the program is closed until it starts the update.
This check is performed like this:
 
bool into = false;
string updatePath = ConfigurationSettings.AppSettings["UpdateFilesPath"];
int counter = 0;
while (!into)
{
    try
    {
        File.Copy(updatePath + @"\" + appName + ".exe", appName + ".exe", true);
        into = true;
    }
    catch
    {
        if (counter > 10)
        {
            return;
        }
        else
  {
            System.Threading.Thread.Sleep(500);
            counter++;
        }
    }
}
 
 
The deletion an copying of the files are done in a seperate thread, so it doesn't interfear with the GUI. The progress is set with thread safe methods. Before the update starts, I count the number of files to be copied and use this to set the progress bar limit. So it will give you a windows like information, if there is a files in the upload that is much bigger then the rest, the progress will not be as accurate. But still it give a better view then nothing, or just a wiating arrow.
When the copy is successful the program will go on to copy all files and if requested first delete all old files. The only files that are not deleted and copied over are the files of the updater itself. So it is really important that your updater is working really good and tested through several times. The update files have to be on the network, I'm currently working on an update of this program that enables you to place the update files on the internet. Then I should rewrite the File.Copy part.
 
That’s why I look at the updater not as a part of any solution but a separate program that can be used throughout all kinds of windows applications.
 
 

 


Self updating windows program

(New post with improved funcionality can be found here.) 

 

In my company, we have a lot of separate tools for monitoring machines, flows, etc., for altering or viewing DB data, and you name it.


As lead .Net developer for my company, I decided to embed all windows applications in the same framework, making it easy to add functionality.   Every PC needed a simple installation and they could use all the functionalities. As the application grew, there was a need to embed security, because not all users have access  to all functionality. So I build in log-in and enhanced security, making it possible to hide each sub application according to the users role. But each time I made these changes to the program, I needed to update all the clients.

At first I was thinking of deploying via IIS (click-once), so we 1 central version, but this was not possible. The security was too tight. Using web-services or remoting could be a solution, but it was too slow. So a windows application was the best in this situation. 

The solution to all these problems was: creating a self updatable program. This challenge was tackled and solved. Not using application blocks, just a very simple solution. Here it is:   

The idea was to place the latest version on a drive map, and all programs would check before starting up if their version was up to date.   The biggest problem you encounter when writing an update procedure is that when you want to copy files, the program needs to be shutdown. You could write a wrapper that handles the update, but then, when the wrapper needs to be updated, you have the same problem. So I found another way. I guess many people have done it this way before, but I couldn't find it on Google.   At the start-up I have this code that calls the check version method:

Assembly asm = Assembly.GetExecutingAssembly();
//Check registration and version
CheckRegistration(asm.GetName().Version.ToString());
 
 

The checkregistration method handles the actual update, also writes the version to the database, so I can track the installed versions. 

       BU_BRSApps.Logic.BRSData data = new BU_BRSApps.Logic.BRSData();
       string compName = System.Windows.Forms.SystemInformation.ComputerName;
       if (!CheckVersion(currentVersion, ref string newVersion )){ 
DialogResult res = MessageBox.Show("Program needs to be updated, update now?", 
"Update",MessageBoxButtons.YesNo);
        if (res == DialogResult.Yes)
        {
MessageBox.Show("Program will restart automatically in a few seconds.");
               data.DeleteRegistration(compName);
               GeneralFunctions.ProcessBatchFile("updater.bat");
               data.InsertRegistration(compName, newVersion);
               this.Dispose(true);
               this.Close();
        }
}
 

The first methods you encounter is the CheckVersion method, this is to check the current version against the one on the file share. Here's the code for that: 

 
private bool CheckVersion(string currentVersion, ref string newVersion)
{
        BU_BRSApps.Logic.BRSData data = new BU_BRSApps.Logic.BRSData();
        newVersion = data.GetRegistration("LatestVersion");
        if (newVersion == currentVersion)
        {
               return true;
        }
        return false;
}
 
 
 

If the assemblies are different, it means that a new version is available on the file share and the current version needs to be updated. Now the trick on how to do the actual update:    

 MessageBox.Show("Program will restart automatically in a few seconds.");
data.DeleteRegistration(compName);
GeneralFunctions.ProcessBatchFile("updater.bat");
data.InsertRegistration(compName, currentVersion);
this.Dispose(true);
this.Close();
 
 
 
 

First I delete the current version in the database, then I open the updater.bat file in a new process. When this process is started I insert the new version and close the current application. The ProcessBatchFile method opens the updater.bat file, this bat file is copied to the output directory and looks like this:   

 
 
ping 127.0.0.1
copy M:\MRD\BRSSupport
BRSupport.exe
exit
 
 

The first thing the bat file does is ping to the local adress, so the program has time to close down. Then it starts to copy the new files and when this is finished, it opens the application again. This process only takes a few seconds. During this time the user has no interaction because I set the process to run in the background. But I warn the user of this before they choose to update. After some testing it appears to be working fine. I'm going to test it some more to see if the time the ping takes is long enough for the slowest systems on the network.  

I know there are better solutions, I also know this works for me. If you have suggestions or ways to self-update a program better, please post comments. One thing I thaught of was: instead of using the .bat, a seperate exe file that does the work. This way I could interact better with the user. But no time for this yet.   In my company, fast and good solutions are needed, this one I had to think of and develop in 1 or 2 days max.

Go to part 2