// get or create an reference to the given entity in the UserFolder EntityRefs list
            public Item GetEntityRef(User user, ServerEntity entity)
            {
                Item entityRefsList = GetEntityRefsList(user);

                if (entityRefsList == null)
                {
                    return(null);
                }

                var entityID = entity.ID.ToString();

                try
                {   // get existing reference to given entity
                    if (storage.Items.Include("FieldValues").Any(i => i.UserID == user.ID && i.FolderID == entityRefsList.FolderID && i.ParentID == entityRefsList.ID &&
                                                                 i.FieldValues.Any(fv => fv.FieldName == FieldNames.EntityRef && fv.Value == entityID)))
                    {
                        return(storage.Items.Include("FieldValues").Single(i => i.UserID == user.ID && i.FolderID == entityRefsList.FolderID && i.ParentID == entityRefsList.ID &&
                                                                           i.FieldValues.Any(fv => fv.FieldName == FieldNames.EntityRef && fv.Value == entityID)));
                    }
                    else
                    {   // create new reference to given entity
                        DateTime now             = DateTime.UtcNow;
                        var      entityRefItemID = Guid.NewGuid();
                        var      entityRefItem   = new Item()
                        {
                            ID           = entityRefItemID,
                            Name         = entity.Name,
                            FolderID     = entityRefsList.FolderID,
                            UserID       = user.ID,
                            ItemTypeID   = SystemItemTypes.Reference,
                            ParentID     = entityRefsList.ID,
                            Created      = now,
                            LastModified = now,
                            FieldValues  = new List <FieldValue>()
                            {
                                new FieldValue()
                                {
                                    ItemID = entityRefItemID, FieldName = FieldNames.EntityRef, Value = entityID
                                },
                                new FieldValue()
                                {
                                    ItemID = entityRefItemID, FieldName = FieldNames.EntityType, Value = entity.GetType().Name
                                },
                            }
                        };
                        storage.Items.Add(entityRefItem);
                        storage.SaveChanges();
                        TraceLog.TraceInfo(String.Format("Created entity ref item {0} for user {1}", entity.Name, user.Name));
                        return(entityRefItem);
                    }
                }
                catch (Exception ex)
                {
                    TraceLog.TraceException(String.Format("Created entity ref item {0} for user {1}", entity.Name, user.Name), ex);
                    return(null);
                }
            }
Exemple #2
0
        public static void InitializeSplunkLogging()
        {
            lock (splunkLock)
            {
                // splunk only needs to be initialized once - when trace directory is created
                if (!IsSplunkInitialized)
                {
                    // make sure this only runs in azure
                    if (HostEnvironment.IsAzure)
                    {
                        // configure splunk to monitor trace directory
                        try
                        {
                            // construct the splunk executable path
                            var    programFiles = Environment.GetEnvironmentVariable("ProgramFiles");
                            var    splunkExe    = Path.Combine(programFiles, @"SplunkUniversalForwarder", @"bin", @"Splunk.exe");
                            var    traceDir     = HostEnvironment.TraceDirectory;
                            string cmdline      = String.Format("add monitor {0} -auth admin:changeme", traceDir);

                            // configure the environment for the splunk process
                            ProcessStartInfo startinfo = new ProcessStartInfo();
                            startinfo.CreateNoWindow         = true;
                            startinfo.UseShellExecute        = false;
                            startinfo.FileName               = splunkExe;
                            startinfo.Arguments              = cmdline;
                            startinfo.WorkingDirectory       = traceDir;
                            startinfo.RedirectStandardOutput = true;
                            startinfo.RedirectStandardError  = true;

                            // run the splunk process to start monitoring the directory
                            Process exeProcess = Process.Start(startinfo);
                            string  stdout     = exeProcess.StandardOutput.ReadToEnd();
                            string  stderr     = exeProcess.StandardError.ReadToEnd();
                            exeProcess.WaitForExit();

                            // write the log file and trace the result
                            string message = String.Format("Finished executing {0} {1}\nStdout: {2}Stderr: {3}", splunkExe, cmdline, stdout, stderr);
                            using (var fs = File.Create(Path.Combine(traceDir, SplunkLogFile)))
                                using (var writer = new StreamWriter(fs))
                                {
                                    writer.WriteLine(message);
                                }
                            TraceLog.TraceInfo(message);
                            IsSplunkInitialized = true;
                        }
                        catch (Exception ex)
                        {
                            TraceException("Splunk initialization failed", ex);
                        }
                    }
                }
            }
        }
Exemple #3
0
 public static void Initialize()
 {
     // create the queue if it doesn't yet exist
     // this call returns false if the queue was already created
     if (Queue.CreateIfNotExist())
     {
         TraceLog.TraceInfo(String.Format("Created queue named '{0}'", queueName));
     }
     else
     {
         TraceLog.TraceDetail(String.Format("Queue named '{0}' already exists", queueName));
     }
 }
 // get or create an Item by name in given folder for given user (include FieldValues if NOT a List)
 public Item GetOrCreateItem(User user, Folder folder, string name, Guid?itemTypeID = null, bool isList = false)
 {
     if (itemTypeID == null)
     {
         itemTypeID = SystemItemTypes.NameValue;
     }
     try
     {   // get the list with given name in given folder
         if (Items.Any(i => i.UserID == user.ID && i.FolderID == folder.ID && i.Name == name))
         {
             if (isList)
             {
                 return(Items.Single(i => i.UserID == user.ID && i.FolderID == folder.ID && i.Name == name));
             }
             else
             {
                 return(Items.Include("FieldValues").Single(i => i.UserID == user.ID && i.FolderID == folder.ID && i.Name == name));
             }
         }
         else
         {   // create new item with given name in given folder
             DateTime now  = DateTime.UtcNow;
             var      item = new Item()
             {
                 ID           = Guid.NewGuid(),
                 Name         = name,
                 FolderID     = folder.ID,
                 UserID       = user.ID,
                 IsList       = isList,
                 ItemTypeID   = itemTypeID.Value,
                 ParentID     = null,
                 Created      = now,
                 LastModified = now
             };
             Items.Add(item);
             SaveChanges();
             TraceLog.TraceInfo(string.Format("Created item named '{0}' in folder '{1}' for user '{2}'", name, folder.Name, user.Name));
             return(item);
         }
     }
     catch (Exception ex)
     {
         TraceLog.TraceException(string.Format("Could not find or create item named '{0}' in folder '{1}' for user '{2}'", name, folder.Name, user.Name), ex);
         return(null);
     }
 }
Exemple #5
0
        public static void WriteTraceFile(string filename, Stream stream)
        {
            try
            {
                bool created = TraceContainer.CreateIfNotExist();
                if (created == true)
                {
                    TraceLog.TraceInfo("Created container " + TraceContainerName);
                }

                var blob = TraceContainer.GetBlobReference(filename);
                blob.UploadFromStream(stream);
                TraceLog.TraceInfo(String.Format("Uploaded trace file {0}", filename));
            }
            catch (Exception ex)
            {
                TraceLog.TraceException(String.Format("Failed to upload trace file {0}", filename), ex);
            }
        }
 // get or create a List by value in given folder for given user
 public Item GetOrCreateListByValue(User user, Folder folder, string value, string name, Guid?itemTypeID = null)
 {
     if (itemTypeID == null)
     {
         itemTypeID = SystemItemTypes.NameValue;
     }
     try
     {   // get the list with given value in given folder
         if (Items.Any(i => i.UserID == user.ID && i.FolderID == folder.ID &&
                       i.FieldValues.Any(fv => fv.FieldName == FieldNames.Value && fv.Value == value)))
         {
             return(Items.Single(i => i.UserID == user.ID && i.FolderID == folder.ID &&
                                 i.FieldValues.Any(fv => fv.FieldName == FieldNames.Value && fv.Value == value)));
         }
         else
         {   // create new list with given value and name in given folder
             DateTime now  = DateTime.UtcNow;
             var      list = new Item()
             {
                 ID           = Guid.NewGuid(),
                 Name         = name,
                 FolderID     = folder.ID,
                 UserID       = user.ID,
                 IsList       = true,
                 ItemTypeID   = itemTypeID.Value,
                 ParentID     = null,
                 Created      = now,
                 LastModified = now,
                 FieldValues  = new List <FieldValue>()
             };
             list.GetFieldValue(FieldNames.Value, true).Value = value;
             Items.Add(list);
             SaveChanges();
             TraceLog.TraceInfo(string.Format("Created list by value '{0}' in folder '{1}' for user '{2}'", value, folder.Name, user.Name));
             return(list);
         }
     }
     catch (Exception ex)
     {
         TraceLog.TraceException(string.Format("Could not find or create list by value '{0}' in folder '{1}' for user '{2}'", value, folder.Name, user.Name), ex);
         return(null);
     }
 }
Exemple #7
0
        public static void WriteBlobData(string containerName, string filename, string data)
        {
            try
            {
                var  container = BlobClient.GetContainerReference(containerName);
                bool created   = container.CreateIfNotExist();
                if (created == true)
                {
                    TraceLog.TraceInfo("Created container " + containerName);
                }

                var blob = container.GetBlobReference(filename);
                blob.UploadText(data);
                TraceLog.TraceInfo(String.Format("Added file {0} to container {1}", filename, containerName));
            }
            catch (Exception ex)
            {
                TraceLog.TraceException(String.Format("Failed to add file {0} to container {1}", filename, containerName), ex);
            }
        }
Exemple #8
0
        public static bool DeleteMessage(object message)
        {
            var msg = message as CloudQueueMessage;

            if (msg == null)
            {
                TraceLog.TraceError("Wrong message type: " + message.GetType().Name);
                return(false);
            }

            try
            {
                TraceLog.TraceInfo("Deleting message ID " + msg.Id);
                Queue.DeleteMessage(msg);
                return(true);
            }
            catch (Exception ex)
            {
                TraceLog.TraceException("DeleteMessage failed", ex);
                return(false);
            }
        }
Exemple #9
0
        public static void EnqueueMessage(object obj)
        {
            DataContractJsonSerializer dcs = new DataContractJsonSerializer(obj.GetType());
            var ms = new MemoryStream();

            dcs.WriteObject(ms, obj);
            ms.Position = 0;
            byte[] bytes = new byte[ms.Length];
            int    len   = ms.Read(bytes, 0, (int)ms.Length); // messages can only be 8K so the cast is safe

            if (len < ms.Length)
            {
                var newbytes = new byte[len];
                Array.Copy(bytes, newbytes, len);
                bytes = newbytes;
            }

            var msg = new CloudQueueMessage(bytes);

            Queue.AddMessage(msg);
            TraceLog.TraceInfo(String.Format("Enqueued a {0}: {1}", obj.GetType().Name, obj.ToString()));
        }
Exemple #10
0
 // get or create a Folder by name for given user
 public Folder GetOrCreateFolder(User user, string name, Guid itemTypeID)
 {
     try
     {   // get the folder by name for user
         if (Folders.Any(f => f.UserID == user.ID && f.Name == name))
         {
             return(Folders.Single(f => f.UserID == user.ID && f.Name == name));
         }
         else
         {   // create the folder with given name and itemTypeID for user
             var folderUser = new FolderUser()
             {
                 ID = Guid.NewGuid(), FolderID = Guid.NewGuid(), UserID = user.ID, PermissionID = BuiltSteady.Zaplify.Shared.Entities.Permissions.Full
             };
             var folder = new Folder()
             {
                 ID          = folderUser.FolderID,
                 SortOrder   = 0,
                 Name        = name,
                 UserID      = user.ID,
                 ItemTypeID  = itemTypeID,
                 Items       = new List <Item>(),
                 FolderUsers = new List <FolderUser>()
                 {
                     folderUser
                 }
             };
             Folders.Add(folder);
             SaveChanges();
             TraceLog.TraceInfo(string.Format("Created folder named '{0}' for user '{1}'", name, user.Name));
             return(folder);
         }
     }
     catch (Exception ex)
     {
         TraceLog.TraceException(string.Format("Could not find or create folder named '{0}' for user '{1}'", name, user.Name), ex);
         return(null);
     }
 }
Exemple #11
0
        public static MQMessage <T> DequeueMessage <T>()
        {
            var msg = Queue.GetMessage(TimeSpan.FromMinutes(1.0d));

            if (msg == null)  // GetMessage doesn't block for a message
            {
                return(null);
            }

            TraceLog.TraceDetail(String.Format("Dequeued message ID {0} inserted {1}", msg.Id, msg.InsertionTime.ToString()));
            byte[] bytes = msg.AsBytes;
            var    ms    = new MemoryStream(bytes);
            DataContractJsonSerializer dcs = new DataContractJsonSerializer(typeof(T));
            T             content          = (T)dcs.ReadObject(ms);
            MQMessage <T> returnMessage    = new MQMessage <T>()
            {
                Content = content, MessageRef = msg
            };

            TraceLog.TraceInfo(String.Format("Dequeued a {0}: {1}", content.GetType().Name, content.ToString()));

            return(returnMessage);
        }
Exemple #12
0
        public override bool ProcessCreate(Item item)
        {
            // base method extracts intent
            if (base.ProcessCreate(item))
            {
                return(true);
            }

            // assign category to the grocery item
            // create a new category fieldvalue in the item to process
            var categoryFV = item.GetFieldValue(FieldNames.Category, true);

            // check if the category for this item's name has already been saved under the $User/Grocery list
            // in this case, store the category in the incoming item
            var groceryCategoryFV = GetGroceryCategoryFieldValue(item);

            if (groceryCategoryFV != null && groceryCategoryFV.Value != null)
            {
                categoryFV.Value = groceryCategoryFV.Value;
                return(true);
            }

            // get the "intent" which in this case is the normalized name
            var intentName = item.Name.ToLower();
            var intentFV   = item.GetFieldValue(ExtendedFieldNames.Intent);

            if (intentFV != null && intentFV.Value != null)
            {
                intentName = intentFV.Value;
            }

            // set up the grocery API endpoint
            GroceryAPI gApi = new GroceryAPI();

            gApi.EndpointBaseUri = string.Format("{0}{1}/", HostEnvironment.DataServicesEndpoint, "Grocery");
            TraceLog.TraceDetail("GroceryAPI Endpoint: " + gApi.EndpointBaseUri);

            // try to find the category from the local Grocery Controller
            try
            {
                var results = gApi.Query(GroceryQueries.GroceryCategory, intentName).ToList();

                // this should only return one result
                if (results.Count > 0)
                {
                    // get the category
                    foreach (var entry in results)
                    {
                        categoryFV.Value = entry[GroceryQueryResult.Category];
                        if (!String.IsNullOrEmpty(entry[GroceryQueryResult.ImageUrl]))
                        {
                            item.GetFieldValue(FieldNames.Picture, true).Value = entry[GroceryQueryResult.ImageUrl];
                        }
                        // only grab the first category
                        break;
                    }
                    TraceLog.TraceInfo(String.Format("Grocery API assigned {0} category to item {1}", categoryFV.Value, item.Name));
                    return(true);
                }
            }
            catch (Exception ex)
            {
                TraceLog.TraceException("Grocery API or database commit failed", ex);
            }

            // use the Supermarket API to get the grocery category
            SupermarketAPI smApi = new SupermarketAPI();

#if FALSE   // use the synchronous codepath for now
            // execute the call asynchronously so as to not block the response
            smApi.BeginQuery(SupermarketQueries.SearchByProductName, item.Name, new AsyncCallback((iar) =>
            {
                try
                {
                    var results = smApi.EndQuery(iar);

                    // find the item using a new context
                    var context           = Storage.NewUserContext;
                    var groceryItem       = context.Items.Single(i => i.ID == item.ID);
                    FieldValue categoryFV = groceryItem.GetFieldValue(FieldNames.Category, true);

                    // get the category
                    foreach (var entry in results)
                    {
                        categoryFV.Value = entry[SupermarketQueryResult.Category];
                        // only grab the first category
                        TraceLog.TraceInfo(String.Format("ProcessCreate: assigned {0} category to item {1}", categoryFV.Value, item.Name));
                        return(true);
                    }
                }
                catch (Exception ex)
                {
                    TraceLog.TraceException("ProcessCreate: Supermarket API or database commit failed", ex);
                }
            }), null);
#else
            try
            {
                var results = smApi.Query(SupermarketQueries.SearchByProductName, intentName);

                // get the category and image
                foreach (var entry in results)
                {
                    categoryFV.Value = entry[SupermarketQueryResult.Category];
                    if (!String.IsNullOrEmpty(entry[SupermarketQueryResult.Image]))
                    {
                        item.GetFieldValue(FieldNames.Picture, true).Value = entry[SupermarketQueryResult.Image];
                    }

                    // write the data to the blob store
                    BlobStore.WriteBlobData(BlobStore.GroceryContainerName, entry[SupermarketQueryResult.Name], entry.ToString());

                    // only grab the first category
                    TraceLog.TraceInfo(String.Format("Supermarket API assigned {0} category to item {1}", categoryFV.Value, item.Name));
                    return(true);
                }
            }
            catch (Exception ex)
            {
                TraceLog.TraceException("Supermarket API or database commit failed", ex);
            }
#endif
            return(false);
        }
        // update constants in Suggestion database to current version defined in WorkflowConstants
        public bool VersionConstants(string me)
        {
            try
            {
                bool updateDB = false;
                if (Versions.Any(v => v.VersionType == DatabaseVersion.Constants && v.VersionString == WorkflowConstants.ConstantsVersion) == false)
                {   // no database - create and lock the new version entry
                    TraceLog.TraceInfo(String.Format("Suggestions database version {0} not found", WorkflowConstants.ConstantsVersion));

                    // remove any existing database version (there should never be more than one)
                    foreach (var existingVersion in Versions.Where(v => v.VersionType == DatabaseVersion.Constants).ToList())
                    {
                        Versions.Remove(existingVersion);
                    }
                    SaveChanges();

                    // create the new version entry
                    DatabaseVersion ver = new DatabaseVersion()
                    {
                        VersionType   = DatabaseVersion.Constants,
                        VersionString = WorkflowConstants.ConstantsVersion,
                        Status        = me
                    };
                    Versions.Add(ver);
                    SaveChanges();
                    updateDB = true;
                }
                else
                {
                    var dbVersion = Versions.Single(v => v.VersionType == DatabaseVersion.Constants && v.VersionString == WorkflowConstants.ConstantsVersion);
                    if (dbVersion.Status == DatabaseVersion.Corrupted)
                    {   // try to update the database again - take a lock
                        TraceLog.TraceInfo("Suggestions database corrupted");
                        dbVersion.Status = me;
                        SaveChanges();
                        updateDB = true;
                    }
                }
                if (updateDB == false)
                {
                    TraceLog.TraceInfo(String.Format("Suggestions database version {0} is up to date", WorkflowConstants.ConstantsVersion));
                    return(true);
                }
            }
            catch (Exception ex)
            {
                TraceLog.TraceException("Could not find database version", ex);
                return(false);
            }

            // update the default database values
            DatabaseVersion           version        = null;
            SuggestionsStorageContext versionContext = Storage.NewSuggestionsContext;

            try
            {   // verify that this unit of execution owns the update lock for the database version
                version = versionContext.Versions.Single(v => v.VersionType == DatabaseVersion.Constants && v.VersionString == WorkflowConstants.ConstantsVersion);
                if (version.Status != me)
                {
                    return(true);
                }

                TraceLog.TraceInfo(String.Format("{0} updating Suggestions database to version {1}", me, WorkflowConstants.ConstantsVersion));

                // remove existing intents
                foreach (var entity in Intents.ToList())
                {
                    Intents.Remove(entity);
                }
                var intents = WorkflowConstants.DefaultIntents();
                if (intents == null)
                {
                    TraceLog.TraceError("Could not find or load intents");
                    version.Status = DatabaseVersion.Corrupted;
                    versionContext.SaveChanges();
                    return(false);
                }
                // add current intents
                foreach (var entity in intents)
                {
                    Intents.Add(entity);
                }
                SaveChanges();
                TraceLog.TraceInfo("Replaced intents");

                // remove existing workflow types
                foreach (var entity in WorkflowTypes.ToList())
                {
                    WorkflowTypes.Remove(entity);
                }
                var workflowTypes = WorkflowConstants.DefaultWorkflowTypes();
                if (workflowTypes == null)
                {
                    TraceLog.TraceError("Could not find or load workflow definitions");
                    version.Status = DatabaseVersion.Corrupted;
                    versionContext.SaveChanges();
                    return(false);
                }
                // add current workflow types
                foreach (var entity in workflowTypes)
                {
                    WorkflowTypes.Add(entity);
                }
                SaveChanges();
                TraceLog.TraceInfo("Replaced workflow types");

                // save the new version number
                version.Status = DatabaseVersion.OK;
                versionContext.SaveChanges();

                return(true);
            }
            catch (Exception ex)
            {
                TraceLog.TraceException("VersionConstants failed", ex);
                // mark the version as corrupted
                version.Status = DatabaseVersion.Corrupted;
                versionContext.SaveChanges();
                return(false);
            }
        }
Exemple #14
0
        // update constants in User database to current version defined in EntityConstants
        public bool VersionConstants(string me)
        {
            try
            {
                bool updateDB = false;
                if (Versions.Any(v => v.VersionType == DatabaseVersion.Constants && v.VersionString == UserConstants.ConstantsVersion) == false)
                {   // no database - create and lock the new version entry
                    TraceLog.TraceInfo(String.Format("User database version {0} not found", UserConstants.ConstantsVersion));

                    // remove an existing database version (there should never be more than one)
                    foreach (var existingVersion in Versions.Where(v => v.VersionType == DatabaseVersion.Constants).ToList())
                    {
                        Versions.Remove(existingVersion);
                    }
                    SaveChanges();

                    // create the new version entry
                    DatabaseVersion ver = new DatabaseVersion()
                    {
                        VersionType   = DatabaseVersion.Constants,
                        VersionString = UserConstants.ConstantsVersion,
                        Status        = me
                    };
                    Versions.Add(ver);
                    SaveChanges();
                    updateDB = true;
                }
                else
                {
                    var dbVersion = Versions.Single(v => v.VersionType == DatabaseVersion.Constants && v.VersionString == UserConstants.ConstantsVersion);
                    if (dbVersion.Status == DatabaseVersion.Corrupted)
                    {   // try to update the database again - take a lock
                        TraceLog.TraceInfo("User database corrupted");
                        dbVersion.Status = me;
                        SaveChanges();
                        updateDB = true;
                    }
                }
                if (updateDB == false)
                {
                    TraceLog.TraceInfo(String.Format("User database version {0} is up to date", UserConstants.ConstantsVersion));
                    return(true);
                }
            }
            catch (Exception ex)
            {
                TraceLog.TraceException("Could not find database version", ex);
                return(false);
            }

            // update the default database values
            DatabaseVersion    version        = null;
            UserStorageContext versionContext = Storage.NewUserContext;

            try
            {   // verify that this unit of execution owns the update lock for the database version
                version = versionContext.Versions.Single(v => v.VersionType == DatabaseVersion.Constants && v.VersionString == UserConstants.ConstantsVersion);
                if (version.Status != me)
                {
                    return(true);
                }

                TraceLog.TraceInfo(String.Format("{0} updating User datatbase to version {1}", me, UserConstants.ConstantsVersion));

                // update existing action types, add new action types
                foreach (var entity in UserConstants.DefaultActionTypes())
                {
                    if (ActionTypes.Any(e => e.ActionTypeID == entity.ActionTypeID))
                    {
                        ActionTypes.Single(e => e.ActionTypeID == entity.ActionTypeID).Copy(entity);
                    }
                    else
                    {
                        ActionTypes.Add(entity);
                    }
                }
                SaveChanges();
                TraceLog.TraceInfo("Replaced action types");

                // update existing colors, add new colors
                foreach (var entity in UserConstants.DefaultColors())
                {
                    if (Colors.Any(e => e.ColorID == entity.ColorID))
                    {
                        Colors.Single(e => e.ColorID == entity.ColorID).Copy(entity);
                    }
                    else
                    {
                        Colors.Add(entity);
                    }
                }
                SaveChanges();
                TraceLog.TraceInfo("Replaced colors");

                // update existing permissions, add new permissions
                foreach (var entity in UserConstants.DefaultPermissions())
                {
                    if (Permissions.Any(e => e.PermissionID == entity.PermissionID))
                    {
                        Permissions.Single(e => e.PermissionID == entity.PermissionID).Copy(entity);
                    }
                    else
                    {
                        Permissions.Add(entity);
                    }
                }
                SaveChanges();
                TraceLog.TraceInfo("Replaced permissions");

                // update existing priorities, add new priorities
                foreach (var entity in UserConstants.DefaultPriorities())
                {
                    if (Priorities.Any(e => e.PriorityID == entity.PriorityID))
                    {
                        Priorities.Single(e => e.PriorityID == entity.PriorityID).Copy(entity);
                    }
                    else
                    {
                        Priorities.Add(entity);
                    }
                }
                SaveChanges();
                TraceLog.TraceInfo("Replaced priorities");

                // update existing or add new built-in users
                foreach (var user in UserConstants.DefaultUsers())
                {
                    if (Users.Any(u => u.ID == user.ID))
                    {
                        var existing = Users.Single(u => u.ID == user.ID);
                        existing.Name       = user.Name;
                        existing.Email      = user.Email;
                        existing.CreateDate = user.CreateDate;
                    }
                    else
                    {
                        Users.Add(user);
                    }
                }
                SaveChanges();
                TraceLog.TraceInfo("Replaced users");

                // update existing or add new built-in itemtypes and fields
                foreach (var itemType in UserConstants.DefaultItemTypes())
                {
                    if (ItemTypes.Any(it => it.ID == itemType.ID))
                    {
                        var existing = ItemTypes.Include("Fields").Single(it => it.ID == itemType.ID);
                        existing.Copy(itemType);
                        if (itemType.Fields == null)
                        {
                            continue;
                        }
                        foreach (var field in itemType.Fields)
                        {
                            if (existing.Fields.Any(f => f.ID == field.ID))
                            {
                                var existingField = existing.Fields.Single(f => f.ID == field.ID);
                                existingField.Copy(field);
                            }
                            else
                            {
                                existing.Fields.Add(field);
                            }
                        }
                    }
                    else
                    {
                        ItemTypes.Add(itemType);
                    }
                }
                SaveChanges();
                TraceLog.TraceInfo("Replaced item types and fields");

                // save the new version number
                version.Status = DatabaseVersion.OK;
                versionContext.SaveChanges();

                return(true);
            }
            catch (Exception ex)
            {
                TraceLog.TraceException("VersionConstants failed", ex);

                // mark the version as corrupted
                version.Status = DatabaseVersion.Corrupted;
                versionContext.SaveChanges();
                return(false);
            }
        }